二、分析问题
(1)从Application分析开始:
Application中添加了应用异常捕获并实现自动启动主界面的功能,CrashHandler用于异常的全局捕获:
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
/**
- Created by dingchao on 2018/3/23.
*/
/处理崩溃重叠/
public class UnCeHandler implements Thread.UncaughtExceptionHandler {
private Thread.UncaughtExceptionHandler mDefaultHandler;
public static final String TAG = “CatchExcep”;
MyApplication application;
public UnCeHandler(MyApplication application){
//获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
this.application = application;
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if(!handleException(ex) && mDefaultHandler != null){
//如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
}else{
try{
Thread.sleep(2000);
}catch (InterruptedException e){
Log.e(TAG, "error : ", e);
}
Intent intent = new Intent(application.getApplicationContext(), FraOverActivity.class);
PendingIntent restartIntent = PendingIntent.getActivity(application.getApplicationContext(), 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
//退出程序
AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用
application.finishActivity();
}
}
/**
-
自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
-
@param ex
-
@return true:如果处理了该异常信息;否则没有处理返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
//使用Toast来显示异常信息
new Thread(){
@Override
public void run() {
Looper.prepare();
Toast.makeText(application.getApplicationContext(), “很抱歉,程序出现异常,即将退出.”, Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
return true;
}
}
界面发生重叠后输出后的日志信息:
//用于获取Activity存在的Fragment的数量
List list=getSupportFragmentManager().getFragments();
System.out.println(“Activity Fragment数量…”+list.size());
应用发生异常后又重新启动,从正常显示Activity到崩溃后重新启动onCreate执行了2次:
三、如果解决问题呢?
- 我是这样想的,是否可以在执行Activity的onStop()或onDestroy()函数中执行Fragment销毁操作。
public void removeFragment(){
mFragmentTransaction = getSupportFragmentManager().beginTransaction();
if (mHomeFragment != null) {
mFragmentTransaction.remove(mHomeFragment);
}
if (mOtherFragment != null) {
mFragmentTransaction.remove(mOtherFragment);
}
if (mThirdFragment != null) {
mFragmentTransaction.remove(mThirdFragment);
}
mFragmentTransaction.commit();
}
如果在onDestroy()中执行Fragment销毁操作,但是出现异常后onDestroy并未执行,太失望了,如果重新启动又会出现Fragment重叠现象。
如果在onStop()中执行Fragment销毁操作,可以随便看看现象:
当栈顶Activity执行onCreate()那么栈顶下面的一个Activity会执行onPause()或onStop()函数,那么看看在onStop()销毁Fragment会有什么结果…还没有执行抛出异常操作就因为销毁Fragment而抛出异常,然后重新启动。这样是不可行的额,下面考虑其他方案。。。。。。
- 在onSaveInstanceState()执行Fragment的保存,官方文档可查看Activity生命周期
onSaveInstanceState(Bundle outState)函数中做存储实例状态:
invoked when the activity may be temporarily destroyed, save the instance state here 当Activity面临被销毁的情况下,进行存储一些对象的状态
onCreate(Bundle savedInstanceState)函数恢复实例状态:recovering the instance state 恢复实例状态
构思了…查看谷歌官方文档后有点启发了,我们可以在onSaveInstanceState()中保存应用将要奔溃时,最后一次显示的Fragment的标志或者Tag进行保存,在内存重启后,可以通过标志或者Tag进行恢复。
阅读了以上部分,你会感觉有点迷茫,ragment如何在Activity里面进行呈现,一开始就没有讲述,下面贴出代码了:
如何在Activity中,添加多个Fragment,我选择了操作Fragment的事务管理类(FragmentTransaction)并调用了add()、show()、hide()相关函数:
第一步:gradle文件中添加TabLayout组件的依赖库,方便进行Fragment的添加或者切换
dependencies {
…
//TabLayout依赖
implementation ‘com.android.support:design:29.0.0-alphal’
…
}
第二步:创建Fragment导航和Fragment容器FragmentLayout的布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical”>
<FrameLayout
android:id=“@+id/frameLayout”
android:layout_width=“match_parent”
android:layout_height=“0dp”
android:layout_weight=“1.0” />
<com.google.android.material.tabs.TabLayout
android:id=“@+id/mytab”
android:layout_width=“match_parent”
android:layout_height=“60dp” />
第三步:进行Fragment的添加或者切换操作
分为:开始事务、隐藏所有Fragment、添加或者显示Fragment、提交事务
private String HOME_TAG = “0”, OTHER_TAG = “1”, THIRD_TAG = “2”;
private void switchFragment(int index) {
//第一步:开始事务
mFragmentTransaction = getSupportFragmentManager().beginTransaction();
//第二步:隐藏所有Fragment
hideFragment(mFragmentTransaction);
//第三步:添加或者隐藏Fragment
switch (index) {
case 0:
if (mHomeFragment == null) {
mHomeFragment = new HomeFragment();
mFragmentTransaction.add(R.id.frameLayout, mHomeFragment, HOME_TAG);
} else {
mFragmentTransaction.show(mHomeFragment);
}
break;
case 1:
if (mOtherFragment == null) {
mOtherFragment = new OtherFragment();
mFragmentTransaction.add(R.id.frameLayout, mOtherFragment, OTHER_TAG);
} else {
mFragmentTransaction.show(mOtherFragment);
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
我的面试经验分享可能不会去罗列太多的具体题目,因为我依然认为面试经验中最宝贵的不是那一个个具体的题目或者具体的答案,而是结束面试时,那一刻你的感受以及多天之后你的回味~
很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我整理了一些资料,需要的可以免费分享给大家
在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
【算法合集】
[外链图片转存中…(img-1s0MDn6Y-1711961877578)]
【延伸Android必备知识点】
[外链图片转存中…(img-4Kv0MIIt-1711961877578)]
【Android部分高级架构视频学习资源】
**Android精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!