作为一名程序员当然是异常越少越好,但有时候一些异常可能是不可避免或者是我们还未预测到,这时候程序会强行关闭,即平常所说的forceclose弹窗,那么什么时候会出现forceclose弹窗呢?
1,forceclose出现原因
forceclose,意为强行关闭,当前应用程序发生了冲突
NullPointExection(空指针),IndexOutOfBoundsException(角标越界)等等一系列未捕获异常
2,避免forceclose方案
首先是尽可能的保证程序不出这些异常,如果有些异常实在不可避免而又不想让程序弹出forceclose弹窗,可以使用UncaughtExceptionHandler。。当程序出现未捕获异常时会去调用UncaughtExctionHandler中的uncaughtException方法,我们要做的就是实现UncaughtExceptionHandler类,自行处理未捕获异常,代码如下:
import java.lang.Thread.UncaughtExceptionHandler; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.os.Process; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.TextView; public class MainActivity extends Activity implements UncaughtExceptionHandler, OnClickListener{ private List<String> mList = new ArrayList<String>(); private TextView mTv; private int pid; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i("tag", "--->>onCreate"); initView(); Thread.setDefaultUncaughtExceptionHandler(this); } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); Log.i("tag", "--->>onstart"); } @Override protected void onRestart() { // TODO Auto-generated method stub super.onRestart(); Log.i("tag", "--->>onRestart"); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); Log.i("tag", "--->>onresume"); } /** * 初始化控件 */ private void initView() { mTv = (TextView) findViewById(R.id.tv); mTv.setOnClickListener(this); } @Override public void uncaughtException(Thread arg0, Throwable arg1) { // TODO Auto-generated method stub Log.i("tag", "截获到forceclose,异常原因为:" + "\n" + arg1.toString()); finish();//结束当前activity } @Override public void onClick(View arg0) { // TODO Auto-generated method stub switch (arg0.getId()) { case R.id.tv: mList.get(1) ;//产生异常 break; default: break; } } @Override protected void onPause() { super.onPause(); Log.i("tag", "--》onpause"); } @Override protected void onStop() { // TODO Auto-generated method stub super.onStop(); Log.i("tag", "--->onstop"); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); Log.i("tag", "-->ondestroy"); } }
接下来,看log日志的结果:
成功捕获到了异常,而且activity也退出了,可是并不是安全退出,因为当你再次点击打开apk时,发现程序无响应,出现的错误log如下:
程序加载activity超时,这涉及到activity的启动过程,大家可以参考老罗的博客,里边儿介绍的很详细
为了解决上述问题,我在uncaughtException方法里将进程杀死,杀死进程有好多中方法,在此列举一个自杀式方法
修改如下:
@Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); pid = android.os.Process.myPid();//获取到本应用程序的pid Log.i("tag", "--->>onstart"); }
@Override public void uncaughtException(Thread arg0, Throwable arg1) { // TODO Auto-generated method stub Log.i("tag", "截获到forceclose,异常原因为:" + "\n" + arg1.toString()); Process.killProcess(pid);//杀死进程 }
其他程序未变。。
3,我们不仅可以在主线程中这么做,还可以在子线程中进行:
private class ChildThread implements Runnable, UncaughtExceptionHandler{ @Override public void run() { // TODO Auto-generated method stub Thread.setDefaultUncaughtExceptionHandler(this); } @Override public void uncaughtException(Thread arg0, Throwable arg1) { // TODO Auto-generated method stub Log.i("tag", "childThread"); } }然后在activity的生命周期中开启子线程,监听未捕获异常的发生