关于程序forceclose时优雅退出解决方案

时间:2022-12-18 11:20:50

作为一名程序员当然是异常越少越好,但有时候一些异常可能是不可避免或者是我们还未预测到,这时候程序会强行关闭,即平常所说的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日志的结果:

关于程序forceclose时优雅退出解决方案

成功捕获到了异常,而且activity也退出了,可是并不是安全退出,因为当你再次点击打开apk时,发现程序无响应,出现的错误log如下:

关于程序forceclose时优雅退出解决方案

程序加载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的生命周期中开启子线程,监听未捕获异常的发生