Android 应用运行期间系统配置(系统语言、字体大小等)改变引发的问题修改

关于此问题的官方文档:https://developer.android.com/guide/topics/resources/runtime-changes.html

问题:系统配置发生改变后,会导致back stack中的activity重新走一遍生命周期,从而会引发一些逻辑问题以及状态显示相关的问题。

解决方法:1.按官方文档来。

       缺点:很明显,需要制定规范,每个activity都需要注意,沟通+维护都会有潜在问题。

       2.由于项目中遇到此问题已经处于维护阶段,针对每个activity按官方文档修改已不太现实,只能简单粗暴的修改:

      (1) 当前处于非主界面,系统配置发生变化后跳转至主界面(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK

      (2)所有activity中带有fragment的,对fragments进行缓存,activity创建时优先读取缓存对fragment

 

代码:

AndroidManifest登录成功的主界面会监听配置改变的事件:

1 <activity
2     android:name=".activity.MainActivity"
3     android:configChanges="locale|layoutDirection|navigation|fontScale"
4     android:screenOrientation="portrait">
5 </activity>

MainActivity监听:

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        Logger.i("@@@@@@","ON Main Activity Cfg change ");

        super.onConfigurationChanged(newConfig);

        Intent goToMainActivity = new Intent(getApplicationContext(), MainActivity.class);
        goToMainActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);; // Will clear out your activity history stack till now
        startActivity(goToMainActivity);
    }

 

带有fragment的activity(以下为使用ViewPager管理fragment的修改方法):

重写onResumeFragments方法,把fragment放入fragmentManager中进行缓存

1 @Override
2     protected void onSaveInstanceState(Bundle outState) {
3         super.onSaveInstanceState(outState);
4         android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
5         fragmentManager.putFragment(outState, ChannelsFragment.class.getName(), fmChannels);
6         Logger.d(LOG_TAG,"mainActivity onSaveInstanceState");
7     }

onCreate时尝试从缓存中读取:

1     if(savedInstanceState!=null){
2             Logger.d(LOG_TAG,"mainActivity onCreate");
3             fmChannels = (ChannelsFragment) getSupportFragmentManager().getFragment(savedInstanceState,ChannelsFragment.class.getName());
8 }
     if(fmChannels==null){
      Logger.d(LOG_TAG,"fmChannels is null");
    fmChannels = new ChannelsFragment();
     }

 

关于VIewPager使用缓存fragment链接:https://stackoverflow.com/questions/7951730/viewpager-and-fragments-whats-the-right-way-to-store-fragments-state

里面提到了使用FragmentPageAdapter.instantiateItem(View, int)同样也可以实现缓存读取,也更方便一点。

  附阿里Android开发手册中:

添 加 Fragment 时 , 确 保 FragmentTransaction#commit() 在 Activity#onPostResume()或者 FragmentActivity#onResumeFragments()内调用。 不要随意使用 FragmentTransaction#commitAllowingStateLoss()来代替,任何 commitAllowingStateLoss()的使用必须经过 code review,确保无负面影响。

推荐的做法是在 Activity 的onPostResume() 或 onResumeFragments() ( 对 FragmentActivity ) 里 执 行 FragmentTransaction.commit(),如有必要也可在 onCreate()里执行。不要随意改用FragmentTransaction.commitAllowingStateLoss()或者直接使用 try-catch 避免crash,这不是问题的根本解决之道,当且仅当你确认 Activity 重建、恢复状态时,本次 commit 丢失不会造成影响时才可这么做。

正例:

public class MainActivity extends FragmentActivity { FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2);
fragmentManager = getSupportFragmentManager(); FragmentTransaction ft = fragmentManager.beginTransaction(); MyFragment fragment = new MyFragment(); ft.replace(R.id.fragment_container, fragment);
ft.commit();
} }

反例:

public class MainActivity extends FragmentActivity { FragmentManager fragmentManager; @Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState); fragmentManager = getSupportFragmentManager(); FragmentTransaction ft = fragmentManager.beginTransaction(); MyFragment fragment = new MyFragment(); ft.replace(R.id.fragment_container, fragment);
ft.commit(); }
}

 

posted on 2018-03-05 18:48  kelisi_king  阅读(791)  评论(0编辑  收藏  举报