美文网首页
处理耗时任务的三种方法

处理耗时任务的三种方法

作者: 学习不断 | 来源:发表于2017-12-05 16:33 被阅读54次

    第一种:Thread

    new Thread(new Runnable() {

    @Override

        public void run() {

    //do your work

    }

    }).start();

    // 更新主线程UI,跑在主线程。

    runOnUiThread(new Runnable() {

    @Override

    public void run() {

    // TODO Auto-generated method stub

    progressBar.setVisibility(View.GONE);

    btn.setText("更新完毕!");

    }

    });

    }

    }).start();

    }

    });

    其实这样的写法弊端很多...

    1.new Thread新建线程性能差

    2.线程缺乏统一管理, 可能无限制的新建线程,导致资源紧缺甚至oom

    3.如若是匿名Thread类, 匿名类会隐式持有外部类,可能导致内存泄露;

    第二种:AsyncTask(异步任务处理)

    在使用AsyncTask时处理类需要继承AsyncTask,提供三个泛型参数,并且重载AsyncTask的四个方法(至少重载一个)。

    三个泛型参数:

    1.Param 任务执行器需要的数据类型

    2.Progress 后台计算中使用的进度单位数据类型

    3.Result 后台计算返回结果的数据类型

    在设置参数时通常是这样的:String... params,这表示方法可以有0个或多个此类型参数;有时参数可以设置为不使用,用Void...即可。

    四个方法:

    1.onPreExecute() 执行预处理,它运行于UI线程,可以为后台任务做一些准备工作,比如绘制一个进度条控件。

    2.doInBackground(Params...) 后台进程执行的具体计算在这里实现,doInBackground(Params...)是AsyncTask的关键,此方法必须重载。在这个方法内可以使用publishProgress(Progress...)改变当前的进度值。

    3.onProgressUpdate(Progress...) 运行于UI线程。如果在doInBackground(Params...) 中使用了publishProgress(Progress...),就会触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。

    4.onPostExecute(Result) 运行于UI线程,可以对后台任务的结果做出处理,结果就是doInBackground(Params...)的返回值。此方法也要经常重载,如果Result为null表明后台任务没有完成(被取消或者出现异常)。

    示例:

    newAsyncTask() {

    @Override

    protectedObject doInBackground(Object... params) {

    //LinkedList queue = new LinkedList();

    //queue.addAll(list);

    FindAddressManager findAddressManager =newFindAddressManager(mContext);

    findAddress2(list, findAddressManager);

    return null;

    }

    }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,null,null);

    第三种:线程池

    //新建一个线程数为3的定长线程池

    ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

    //执行

    fixedThreadPool.execute(new Runnable() {

    @Override

    public void run() {

    //xxx

    }

    });

    第四种:Service

    Service作为Android四大组件之一,在每一个应用程序中都扮演着非常重要的角色。它主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。

    关于Service最基本的用法自然就是如何启动一个Service了,启动Service的方法和启动Activity很类似,都需要借助Intent来实现,下面我们就通过一个具体的例子来看一下。

    public class MyService extends Service {

    public static final String TAG ="MyService";

    @Override

    public void onCreate() {

    super.onCreate();

    Log.d(TAG,"onCreate() executed");

    }

    @Override

    public int onStartCommand(Intent intent,int flags,int startId) {

    Log.d(TAG,"onStartCommand() executed");

    return super.onStartCommand(intent, flags, startId);

    }

    @Override

    public void onDestroy() {

    super.onDestroy();

    Log.d(TAG,"onDestroy() executed");

    }

    @Override

    public IBinder onBind(Intent intent) {

    return null;

    }

    }

    另外需要注意,项目中的每一个Service都必须在AndroidManifest.xml中注册才行

    onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了,不管怎样调用startService()方法,onCreate()方法都不会再执行。因此你可以再多点击几次Start Service按钮试一次,每次都只会有onStartCommand()方法中的打印日志。

    IntentService

    IntentService是系统提供给我们的一个已经继承自Service类的特殊类,IntentService特殊性是相对于Service本身的特性而言的:

    1.默认直接实现了onBind(..)方法,直接返回null,并定义了抽象方法onHandlerIntent(..),用户自定义子类时,需要实现此方法;

    2.onHandlerIntent(..)主要就是用来处于相应的”长期“任务的,并且已经自动在新的线程中,用户无语自定义新线程;

    3.当”长期“任务执行完毕后(也就是onHandlerIntent(..)执行完毕后),此IntentService将自动结束,无需人为调用方法使其结束;

    4.IntentService处于任务时,也是按照队列的方式一个个去处理,而非真正意义上的多线程并发方式。

    下面是一个基本的继承自IntentService的自定义Service:

    public class MyIntentService extends IntentService {

    public static final String TAG = "MyIntentService";

         public MyIntentService() {

             super(TAG);

         }

         public MyIntentService(String name) {

             super(name);

         }

    @Override

    protected void onHandleIntent(Intent intent) {

    Log.w(TAG, "in onHandleIntent");

    Log.w(TAG, "thread name:" + Thread.currentThread().getName());

         }

    }

    相关文章

      网友评论

          本文标题:处理耗时任务的三种方法

          本文链接:https://www.haomeiwen.com/subject/gooxixtx.html