从 MainActivity 修改 Fragment 的视图

Modify Fragment's views from MainActivity

我正在尝试使用 android 实现滑动视图。我正在使用带有两个包含片段的选项卡的 ViewPager。在我的 onCreate() 方法中,我试图从 sharedPreferences 中读取,并根据我得到的内容,我想将文本和可见性更改为第一个片段的父视图的某些子视图。不幸的是,当我尝试访问片段视图时,我总是得到 NullPointerException。

下面给出了我来自两个片段之一的示例代码。请你帮助我好吗 ?有更好的方法吗?

主要活动:

    @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

...}

片段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;
}

有什么不明白的地方欢迎提问。谢谢

据我了解,您 activity 调用 setSettings 来更改片段中的视图。您没有提供堆栈跟踪,我认为您有问题 - 在 offcreen 片段中调用 onPause 后尝试更改视图。有几种方法可以处理它。 首先不要直接调用视图。
在 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();
    ...}

碎片化

@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

                            }
                        }
                    }
                }
            );
        }
    }

你也可以用Otto busactivity分片通信还是不合适,因为分片可以处于!isResumed状态,但对分片-[=32很有用=] 通讯.
如果您需要对每个片段进行一些复杂的状态跟踪并且 activity 分开,我建议使用 sqlDatabase and CursorLoaders。它会让你很好地控制状态和即时通信。

编辑:
这并不是说您不能使用吸气剂将视图从片段传递到 activity。
问题 - 你不能保证你完全了解片段和视图的状态。您尝试更新 activity 的 onStart 上的视图,这是较早调用的,然后是 fragment 的 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`。请参阅 android 工作室 activity 和片段模板)。因此,当您调用更改视图时,片段和视图可能不存在。
此外,您应该阅读片段和 activity 生命周期并阅读上下文(尤其是为什么不相关的上下文持有者中的强引用视图会导致严重的内存泄漏和 lificle 错误