Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify Fragment's views from MainActivity

I am trying to implement swipe views with android. I am using a ViewPager with two tabs containing fragments. In my onCreate() method, I am trying to read from a sharedPrefferences and according to what i am getting, i want to change text and visibility to some child views of the parent view of the first fragment. Unfortunately i am always getting NullPointerException when i am trying to access fragments views.

My sample code from the one of the two fragments is given below. Could you please help me ? Is there a better way to do so?

MainActivity:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    actionBar = getActionBar();
    context = getApplicationContext();
    myTabPagerAdapter = new TabPagerAdapter(getSupportFragmentManager());

    myViewPager = (ViewPager) findViewById(R.id.pager);
    myViewPager.setAdapter(myTabPagerAdapter);
    myViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            Toast.makeText(MainActivity.this, "Selected page position: " + position, Toast.LENGTH_SHORT).show();
            getActionBar().setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    ActionBar.TabListener tabListener = new ActionBar.TabListener() {

        @Override
        public void onTabReselected(android.app.ActionBar.Tab tab, FragmentTransaction ft) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
            myViewPager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(android.app.ActionBar.Tab tab, FragmentTransaction ft) {
            // TODO Auto-generated method stub
        }
    };
    actionBar.addTab(actionBar.newTab().setText("Spot Position").setTabListener(tabListener));
    actionBar.addTab(actionBar.newTab().setText("Track Vehicle").setTabListener(tabListener));


    //Get saved latitude and longitude from sharedPreferences
    sharedPref = context.getSharedPreferences("net.ddns.drimou.bachelorthesis", Context.MODE_PRIVATE);
    editor = sharedPref.edit();



}

@Override
protected void onStart() {
    super.onStart();
    getSharedPreferencesOnStart();
}

public void getSharedPreferencesOnStart() {

        String s = myTabPagerAdapter.makeFragmentName(myViewPager.getId(),myViewPager.getCurrentItem());
        SpotPosition sp =  (SpotPosition) myTabPagerAdapter.getItem(0);
        sp.setSettings();//In this call i am getting null pointer

...}

Fragment A

public class SpotPosition extends Fragment {


TextView locationTextView;



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View spotPosition = inflater.inflate(R.layout.spot_position, container, false);

    return spotPosition;


}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}

public void setSettings(){
    locationTextView = (TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
    locationTextView.setVisibility(View.VISIBLE);
    locationTextView.setText("Hello");
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public void onDestroyView() {
    super.onDestroyView();
}

TabPagerAdapter

public class TabPagerAdapter extends FragmentPagerAdapter {

SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
private View mCurrentView;
private SpotPosition sp = null;
private static int NUM_ITEMS = 2;

public TabPagerAdapter(FragmentManager fm) {
    super(fm);
}

@Override
public Fragment getItem(int i) {
    switch (i) {
        case 0:
            //Fragment for SpotPosition myViewPager
            return new SpotPosition();
        case 1:
            //Fragment for TrackVehicle myViewPager
            return new TrackVehicle();
    }
    return null;

}

@Override
public int getCount() {
    return NUM_ITEMS; //Number of Tabs
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment fragment = (Fragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    sp = (SpotPosition)object;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}

@Override
public CharSequence getPageTitle(int position) {
    switch(position) {
        case 0:
            return "Spot Position";
        case 1:
            return "Track Vehicle";
        default:
            return null;
    }
}

public String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

public Fragment getRegisteredFragment(int position) {
    return registeredFragments.get(position);
}

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

public View getCurrentView(){
    return this.mCurrentView;
}

public SpotPosition getCurrentSpotPosition(){
    return this.sp;
}

Feel free to ask if something is not understood. Thank you

like image 802
JD7 Avatar asked Dec 21 '25 01:12

JD7


1 Answers

As far as I understand you call setSettings from you activity, to change views in you fragment. You did not provide stacktrace and i assume you problem - attempt to change view after onPause was called in offcreen fragment. There are several ways to deal with it. First of all dont call to views dirrectly.
On activity

    public void getSharedPreferencesOnStart() {

            String s = myTabPagerAdapter.makeFragmentName(myViewPager.getId(),myViewPager.getCurrentItem());
            SpotPosition sp =  (SpotPosition) myTabPagerAdapter.getItem(0);

            // sp.setSettings();//In this call i am getting null pointer
            SharedPreferences prefs = getSharedPreferences("message",MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putBoolean("say_hello",true")
editor.commit();
    ...}

in fragments

@Override
    public void onResume(){
        super.onResume();
        SharedPreferences prefs =
            getActivity().getSharedPreferences("message", Context.MODE_PRIVATE);
        {
            //this block is used for offsreen fragment, it will get update, when it go to forescreen
            boolean sayHello = prefs.getBoolean("say_hello", false);
            if(sayHello){
                locationTextView =
                    (TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
                locationTextView.setVisibility(View.VISIBLE);
                locationTextView.setText("Hello");
            }else{
                // say something elese
            }
        }
        {
            //this listener is for forescreen fragment, as soon as shared preferences will be updated,
            // listerner willbe called  and you can update your view depending on changed parameters
            prefs.registerOnSharedPreferenceChangeListener(
                new OnSharedPreferenceChangeListener(){

                    @Override
                    public void onSharedPreferenceChanged(
                        SharedPreferences sharedPreferences, String key
                    ){
                        if(key.equals("say_hello")){
                            boolean sayHello = sharedPreferences.getBoolean("say_hello", false);
                            if(sayHello){
                                locationTextView =
                                    (TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
                                locationTextView.setVisibility(View.VISIBLE);
                                locationTextView.setText("Hello");
                            }else{
                                // say something elese

                            }
                        }
                    }
                }
            );
        }
    }

You also can use Otto bus it is still unsutable for activity to fragment communication, as fragment can be in !isResumed state, but it is usefull fro fragment -activity comunication.
If you need some complex state tracking for each fragment and activity separatly, I'd recomment to use sqlDatabase and CursorLoaders. It will give you good controll over states and instan comunication.

Edit:
Its not that you cannot pass view from fragment to activity with getters.
Problem - you cannot garanty, that you completly aware of state of the fragment and a view. You try to update views on onStart of activity, which is call earlier, then fragmentsonStart, because fragment have to be generated by adapter and go through attachement process. (to find yout if fragment is attached to activity, you have to set listener in activity and call it ononActivityAttached` of fragment. See android studio activity with fragment template). Thus, when you call to change views, fragment and views probably did not exist.
Futhermore you should read about fragment and activity lifecycle and read about context ( espesialy why strong referencing views in unrelated context holder lead to sever memmory leaks and lificle errors

like image 128
Yarh Avatar answered Dec 22 '25 15:12

Yarh