作为一名程序员当然是异常越少越好,但有时候一些异常可能是不可避免或者是我们还未预测到,这时候程序会强行关闭,即平常所说的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的生命周期中开启子线程,监听未捕获异常的发生