在android 中,当我们操作一个事件在5s、10s、20s(按键或触摸事件特定时间内无响应,广播、service特定时间内无法处理完成)就会报anr,为了避免这种问题,那我们就可以使用后台去处理,处理完后然后更新,异步处理一般使用AsyncTask、IntentService、Handler。
1、AsyncTask使用
asyncTask类可以将耗时的操作放到后台线程中处理操作完成后同步更新ui,asyncTask的doInBackground方法用于处理耗时的事件,在后台线程运行,执行完的结果在onProgressUpdate和onPostExecute和ui同步更新、显示,当需要同步更新的时在onProgressUpdate可通过doInBackground的publishProgress传递过去。类中的三个参数,可以根据实际需求写,第一个跟onPostExecute一样,第二个跟doInBackground的一样,第三个跟onProgressUpdate的一样。
private class MyAsyncTask extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... params) {
//在后台执行,可以把运行时间比较长的代码放这里
String result = "";//处理后返回结果
int inputLength = params[0].length();
int myProgress = 0;
while (myProgress<100){
myProgress++;
try {
Thread.sleep(500);
publishProgress(myProgress);
if (myProgress<inputLength) {
result = result + params[0].charAt(inputLength - myProgress);
final String finalResult = result;
runOnUiThread(new Runnable() {
@Override
public void run() {
tvProgress.setText(finalResult);
}
});
}
}catch (InterruptedException e){
//publishProgress(myProgress);
}
Log.e(TAG,"myProgress="+myProgress+ " result="+result);
}
return result;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//和ui线程同步更新,doInBackground执行完然后更新
//通过ui更新、dialog或者notification报告结果
tvProgress.setText(s);
Log.e(TAG,"onPostExecute="+s);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//和ui线程同步更新
//更新进度条,notification或者其他ui
sbBar.setProgress(values[0]);
Log.e(TAG,"values[0]="+values[0]);
}
@Override
protected void onCancelled(String s) {
Log.e(TAG,"onCancelled="+s);
super.onCancelled(s);
}
}
AsyncTask 的启动方式,里面的参数可传可不传,根据实际需求写。
String input = "test ...MainActivity";
// new MyAsyncTask().execute(input);
// new MyAsyncTask().onProgressUpdate(20);l
//new MyAsyncTask().doInBackground(input);
// new MyAsyncTask().onPostExecute(input);
2、通过手动创建线程后台更新,下面简单代码实现
/**
* 在主GUI线程上调用,可同步更新
*/
private void backgroundExecution(){
Thread thread = new Thread(null,doBackgroundThreadProcessing,"Background");
thread.start();
}
private Runnable doBackgroundThreadProcessing = new Runnable() {
@Override
public void run() {
backgroundThreadProcessing();
}
};
/**
* 后台处理耗时操作
*/
int myProgress = 0;
private void backgroundThreadProcessing(){
while (myProgress<10) {
myProgress++;
try {
Thread.sleep(500);
runOnUiThread(new Runnable() {
@Override
public void run() {
tvProgress.setText(myProgress+"");
}
});
} catch (InterruptedException e) {
//publishProgress(myProgress);
}
Log.e(TAG, "myProgress1=" + myProgress);
}
}
使用的话之间调用backgroundExecution();便可。
3、使用IntentService实现
*IntentService是Service的子类,比普通的Service增加了额外的功能,Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中,Service也不是专门一条新线程,因此不应该在Service中直接处理耗时的任务。
*但会创建独立的worker线程来处理所有的Intent请求,
*会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题,所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service,
*为Service的onBind()提供默认实现,返回null,
*为Service的onStartCommand提供默认实现,将请求Intent添加到队列中
简单使用,首先在权限文件中添加
<service android:name=".MyIntentService">
<intent-filter >
<action android:name="com.test"/>
</intent-filter>
</service>
然后创建MyIntentService类,在onHandleIntent中处理耗时任务
package com.example.apple.asynctask;
import android.app.IntentService;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
/**
* Created by apple on 17/6/11.
*/
public class MyIntentService extends IntentService {
private final String TAG = "MyIntentService";
@Override
public void onCreate() {
super.onCreate();
}
public MyIntentService() {
//必须实现父类的构造方法
super("MyIntentService");
}
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG,"onBind=");
return super.onBind(intent);
}
@Override
public void onStart(Intent intent, int startId) {
Log.e(TAG,"onStart=");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG,"onStartCommand=");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
Log.e(TAG,"setIntentRedelivery=");
}
@Override
protected void onHandleIntent(Intent intent) {
//在此处理耗时任务,当处理完service会终止自己
//Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
String action = intent.getExtras().getString("test");
//
if (action.equals("test")){
int myProgress = 0;
while (myProgress<10){
myProgress++;
try {
Thread.sleep(500);
}catch (InterruptedException e){
}
Log.e("ss","myProgress="+myProgress);
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
启动使用:
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("test", "test");
intent.putExtras(bundle);
intent.setPackage(getPackageName()); //在这里添加这行,表示兼容5.0之后
startService(intent);