1. android使用fragment制作的tab页,当主界面切换到后台,在系统内存不足的情况下,主界面被系统强制回收后又被重新create造成fragment重叠。


主界面的tab切换使用了fragment切换来实现,因此主activity继承自v7的AppCompatActivity,而AppCompatActivity继承自FragmentActivity

我们看下FragmentActivity中的onSaveInstanceState方法:

 @Override protected void onSaveInstanceState(Bundle outState) {      super.onSaveInstanceState(outState);      Parcelable p = mFragments.saveAllState();      if (p != null) {          outState.putParcelable(FRAGMENTS_TAG, p);      }      if (mPendingFragmentActivityResults.size() > 0) {                                           outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG,mNextCandidateRequestIndex);            int[] requestCodes = new int[mPendingFragmentActivityResults.size()];            String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()];            for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) {                requestCodes[i] = mPendingFragmentActivityResults.keyAt(i);                fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i);            }            outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes);            outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos);        }    }

在代码中有这么一段

Parcelable p = mFragments.saveAllState();      if (p != null) {          outState.putParcelable(FRAGMENTS_TAG, p);      }

FragmentActivity在onSaveInstanceState中保存了当前界面所有fragment的状态,这就导致了主界面activity在销毁后fragment被onSaveInstanceState保存了下来,在主界面Activity重新回到前台被系统重新创建的时候,原有的fragment的视图状态在FragmentActivity中被还原了回来,同时主界面Activity的oncreate方法又被重新执行了,于是导致了在已有fragment基础上重复创建了fragment。

下面是几种解决方案:

1.在oncreate中判断oncreate方法中传递过来的savedInstanceState是否为null,如果为null执行完整的fragment tab初始化工作,否则不执行初始化,思路代码如下:

@Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        if (savedInstanceState != null) {        //界面正常情况下create时的逻辑            initTab();        }        else {        //界面在内存不足情况下被强制回收后重新create的逻辑        }}

2.这种方法属于懒人方法的一种,在oncreate中在super.oncreate执行前将saveInstance中的fragment状态全部置空,这样在Activity被重新创建的时候原有的fragment都不会被恢复状态,而是按照Activity的正常create执行:

@Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        if (savedInstanceState != null) {            savedInstanceState.putParcelable("android:support:fragments", null);        }        super.onCreate(savedInstanceState);}

3.同样是懒人方法,重写onSaveInstanceState方法,注释对父saveInstanceState的调用,不过这么做会有很多副作用,系统自己实现的onSaveInstanceState就完全失去作用了,所以并不太推荐大家这么去做,参考代码:

  @Override    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {//        super.onSaveInstanceState(outState, outPersistentState);    }

2. App打包成apk后在部分手机上安装,安装完成后直接点击系统安装界面上的打开按钮后点击home键到home页,再点击启动图标,应用重复启动(该问题只出现在第一次安装app的时候,之后退出app再重新运行,点击home,再点击启动图标不会出现该问题)


解决方案,在启动页增加代码判断,如果启动的Activity不是当前任务的根Activity则直接finish掉,代码如下:

    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        setTheme(R.style.AppTheme_NoActionBar);        super.onCreate(savedInstanceState);        //判断根Activity代码        if (!isTaskRoot()) {            finish();            return;        }    }

3. 应用调用系统相机后,返回应用数据丢失,应用崩溃等


在手机上调用系统相机的时候,有很大的几率会导致内存不足从而调用相机的app或者app的调用相机的Activity界面被强制回收,所以调用相机的Activity重写onSaveInstanceState是非常必要的,在onSaveInstanceState方法中将局部变量保存起来,同时在onRestoreInstanceState方法中重新获取这些局部变量并做必要的逻辑处理。


4. 在部分老旧机型上,调用系统相机报Activity Not Found 异常


出现这种错误一般两种情况:

  1. 部分设备没有自带摄像头
  2. 部分设备没有sd卡

为了处理这两种情况,在启动相机的时候做了简单的判断:

private void showCamera() {        String status = Environment.getExternalStorageState();        if (status.equals(Environment.MEDIA_MOUNTED)) {            try {                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);                mTakePhotoUri = FileUtils.getOutputMediaFileUri(FileUtils.MEDIA_TYPE_IMAGE);                mFilePath = mTakePhotoUri.getPath();                intent.putExtra(MediaStore.EXTRA_OUTPUT, mTakePhotoUri);                startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);            } catch (ActivityNotFoundException e) {                showShortToast(R.string.error_no_camera);            }        }        else {            showShortToast(R.string.error_no_sdcard);        }    }

5. 在Android 4.1等设备上使用EventBus报aused by: java.lang.ClassNotFoundException: Didn’t find class “android.os.PersistableBundle” on path: DexPathList


造成这个错误的原因一般是无意中重写了onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)这个方法,检查下自己的代码,使用onSaveInstanceState(Bundle outState)来处理你的代码逻辑

6. 引入图片框架fresco后,出现is 32-bit instead of 64-bit的错误


因为项目中引用了其他第三方的so库,但是却没有arm64-v8目录的so文件,而fresco的库文件中却创建了arm64-v8的目录

按照Android查找so文件的规则,Android设备会优先查找对应的cpu架构目录,如果查找不到对应的目录,会到armeabi目录下兼容方式调用so文件,但是如果能查找到对应的目录,则只会调用该目录下的so库,如果已有的so库没有对应目录下的so文件,那么就会因为找不到对应目录so库从而造成错误。

那么我的项目并没有创建arm64-v8的目录,为什么会出错呢,经过检查后发现,原来我们的fresco库为了兼容性,默认创建了对应的arm64-v8的库目录,而我的项目中其他的so库并没有对应的arm64-v8架构的,所以导致app在安装到arm64位设备上的时候会到arm64-v8的so目录下去查找,从而报了is 32-bit instead of 64-bit的错误。

解决方案:

  1. 为项目已经引用的so库添加对应arm64-v8架构的so库。
  2. 在gradle的defaultConfig中设置

    ndk {  // 设置支持的 SO 库构架,注意这里要根据你的实际情况来设置 abiFilters 'armeabi' , 'x86'}

更多相关文章

  1. android suspend and resume
  2. 细读《深入理解 Android(安卓)内核设计思想》(一)进程间通信与同步
  3. Android相机启动crash错误排查
  4. android自定义字体和程序启动时的加载页面
  5. 如何让自己写的apk获得系统权限
  6. Android应用获取系统属性
  7. Android(安卓)类似美团的选择城市界面
  8. 【 Android(安卓)10 四大组件 】系列 -- Service 的 “ 启动流程
  9. android使用AIDL跨进程通信(IPC)

随机推荐

  1. 从 Android 看智能终端的未来【转】
  2. Android项目复盘4
  3. android ListItem 焦点获取问题
  4. Android:自适应不同分辨率的屏幕大小、方
  5. 离线搭建Android开发环境
  6. Android SurfaceView学习示例
  7. 向虚拟机发短信(android SMS 调试)
  8. SDL2库(3)-Android(安卓)端源码简要分析(V
  9. Android之A面试题④应用程序内部启动Acti
  10. Android中应该注意的细节