Android IntentService和ResultReceiver的異步處理實(shí)現(xiàn)service與activity的交互

使用一個(gè)開(kāi)新工作線(xiàn)程處理一些耗時(shí)任務(wù)后,如何通知到啟動(dòng)它的Activity?

這篇文章主要用的是Android為我們提供的一種封裝好的工具——"ResultReceiver"

【IntentService和ResultReceiver】

service.gif

IntentService繼承自service,在IntentService中我們開(kāi)啟一個(gè)線(xiàn)程執(zhí)行下載任務(wù)(service和你的app其實(shí)是在一個(gè)線(xiàn)程中,因此不想阻塞主線(xiàn)程的話(huà)必須開(kāi)啟新的線(xiàn)程。

//在這里根據(jù)url進(jìn)行下載文件,并通過(guò)receiver把需要更新的progressbar的值放在bundle傳過(guò)去
public class DownloadService extends IntentService {
    public static final int UPDATE_PROGRESS = 8344;
    public DownloadService() {
        super("DownloadService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        String urlToDownload = intent.getStringExtra("url");
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
        HttpURLConnection connection ;
        try {
            URL url = new URL(urlToDownload);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();
            Log.d("test","fileLength:"+fileLength);
            // download the file
            InputStream input = connection.getInputStream();
            OutputStream output = new FileOutputStream("/sdcard/new.apk");
            byte data[] = new byte[2048];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                Bundle resultData = new Bundle();
                resultData.putInt("progress" ,(int) (total * 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
            }
            output.flush();
            output.close();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
//記得注冊(cè)<service android:name=".DownloadService"/>

activity中這樣調(diào)用DownloadService

  progressDialog.show();                                                
  Intent intent = new Intent(this, DownloadService.class);              
  intent.putExtra("url",url);                                           
  intent.putExtra("receiver", new DownloadReceiver(new Handler()));     
  startService(intent);                                                 

activity中定義一個(gè)廣播接收器繼承ResultReceiver,ResultReceiver允許我們接收來(lái)自service中發(fā)出的廣播

 //使用ResultReceiver接收來(lái)自DownloadService的下載進(jìn)度通知                                                                
 private class DownloadReceiver extends ResultReceiver {                                                     
     public DownloadReceiver(Handler handler) {                                                              
         super(handler);                                                                                     
     }                                                                                                       

     @Override                                                                                               
     protected void onReceiveResult(int resultCode, Bundle resultData) {                                     
     super.onReceiveResult(resultCode, resultData);                                                          
         if (resultCode == DownloadService.UPDATE_PROGRESS) {                                                
             int progress = resultData.getInt("progress");                                                   
             //(true)就是根據(jù)你的進(jìn)度可以設(shè)置現(xiàn)在的進(jìn)度值。                                                                     
             //(false)就是滾動(dòng)條的當(dāng)前值自動(dòng)在最小到最大值之間來(lái)回移動(dòng),形成這樣一個(gè)動(dòng)畫(huà)效果                                                    
             progressDialog.setIndeterminate(false);                                                         
             progressDialog.setProgress(progress);                                                           
             if (progress == 100) {                                                                          
                 progressDialog.dismiss();         
          //自動(dòng)安裝下載的apk                                                          
                 File file=new File("/sdcard/new.apk");                                                      
                 Intent installIntent = new Intent(Intent.ACTION_VIEW);                                      
                 installIntent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                 installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                                      
                 startActivity(installIntent);                                                               
             }                                                                                               
         }                                                                                                   
     }                                                                                                       
 }                                                                                                           

說(shuō)明:

1.IntentService是Service類(lèi)的子類(lèi),用來(lái)處理異步請(qǐng)求??蛻?hù)端可以通過(guò)startService(Intent)方法傳遞請(qǐng)求給IntentService,IntentService通過(guò)worker thread處理每個(gè)Intent對(duì)象,執(zhí)行完所有的工作之后自動(dòng)停止Service。說(shuō)明:worker thread處理所有通過(guò)傳遞過(guò)來(lái)的請(qǐng)求,創(chuàng)建一個(gè)worker queue,一次只傳遞一個(gè)intent到onHandleIntent中,從而不必?fù)?dān)心多線(xiàn)程帶來(lái)的問(wèn)題。處理完畢之后自動(dòng)調(diào)用stopSelf()方 法;默認(rèn)實(shí)現(xiàn)了Onbind()方法,返回值為null;

使用IntentService需要兩個(gè)步驟:
1、寫(xiě)構(gòu)造函數(shù)
2、復(fù)寫(xiě)onHandleIntent()方法

2.activity調(diào)用service時(shí),傳遞的廣播接收器需要傳入一個(gè)Handler,并且這個(gè)Handler是可以為null的。這個(gè)Handler的作用只有一個(gè),就是控制回調(diào)函數(shù)執(zhí)行在創(chuàng)建Handler的線(xiàn)程。如果在Activity主線(xiàn)程創(chuàng)建的handler實(shí)例,則回調(diào)也會(huì)在主線(xiàn)程執(zhí)行。就可以直接在回調(diào)中操作UI。也就是在onReceiveResult更新UI。

3.在intentservice中最主要的方法是通過(guò) receiver.send方法就參數(shù)傳遞給activity。源碼就是在調(diào)用send方法的線(xiàn)程中執(zhí)行onReceiveResult回調(diào)。


親,給個(gè)贊鼓勵(lì)一下吧~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容