編輯:Android資訊
官方解釋如下:
//IntentService定義的三個基本點:是什麼?怎麼用?如何work?*/
1、IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand.
2、Clients send requests through startService(Intent) calls;
3、the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
//解釋了IntentService的好處,以及How to use IntentService*/
This “work queue processor” pattern is commonly used to offload tasks from an application’s main thread. The IntentService class exists to simplify this pattern and take care of the mechanics. To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.
All requests are handled on a single worker thread — they may take as long as necessary (and will not block the application’s main loop), but only one request will be processed at a time.
1、IntentService是Service類的子類,用來處理異步請求。
2、客戶端可以通過startService(Intent)方法傳遞請求給IntentService
3、IntentService在onCreate()函數中通過HandlerThread單獨開啟一個線程來處理所有Intent請求對象(通過startService的方式發送過來的)所對應的任務,這樣以免事務處理阻塞主線程。
4、執行完所一個Intent請求對象所對應的工作之後,如果沒有新的Intent請求達到,則自動停止Service;否則執行下一個Intent請求所對應的任務。
5、IntentService在處理事務時,還是采用的Handler方式,創建一個名叫ServiceHandler的內部Handler,並把它直接綁定到HandlerThread所對應的子線程。 ServiceHandler把處理一個intent所對應的事務都封裝到叫做onHandleIntent的虛函數;因此我們直接實現虛函數onHandleIntent,再在裡面根據Intent的不同進行不同的事務處理就可以了。
This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf().
1、該函數用於針對Intent的不同進行不同的事務處理.執行完所一個Intent請求對象所對應的工作之後,如果沒有新的Intent請求達到,
則自動停止Service;否則ServiceHandler會取得下一個Intent請求傳人該函數來處理其所對應的任務。
2、所有請求都在一個單線程中,不會阻塞應用程序的主線程(UI Thread),但是同一時間只處理一個請求。
IntentService的特點:
基於以上,IntentService與Service比較的好處有:
當然,IntentService的缺點也是顯而易見:
由於是單個的worker thread,所以任務需要排隊,不適合大多數的多任務情況;
主要由MainActivity和MyIntentService構成,在MainActivity中啟動服務,並傳遞兩個參數a和b,在MyIntentService中獲取參數,求和,並通過發送廣播的形式向UI返回結果,然後MainActivity在接收到廣播之後更新UI。
代碼如下:
public class MainActivity extends AppCompatActivity { private LinearLayout ll_container; private BroadcastReceiver forSumReceiver=new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.i("TAG","onReceive ()"); if(intent.getAction()==Constans.ACTION_RESULT){ int a=intent.getIntExtra(Constans.A,0); int result=intent.getIntExtra(Constans.RESULT,0); Log.i("TAG","onReceive --result:"+result); handleResult(a,result); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ll_container= (LinearLayout)findViewById(R.id.ll_container); Log.i("TEST","MainActivity:"+android.os.Process.myTid()); registerBroadcast(); } private void handleResult(int a,int result){ TextView textView=(TextView)ll_container.findViewWithTag(a); String old=textView.getText().toString(); String newText=old.replaceAll(" 正在計算中...",String.valueOf(result)+" 計算Success"); textView.setText(newText); } private void registerBroadcast(){ IntentFilter intentFilter=new IntentFilter(); intentFilter.addAction(Constans.ACTION_RESULT); registerReceiver(forSumReceiver,intentFilter); } private int a=1; public void addTask(View view){ int b=new Random().nextInt(101)+1; MyIntentService.startMyIntentService(this,a,b); TextView textView=new TextView(this); textView.setText(a+"+"+b+"= "+ " 正在計算中..."); textView.setTag(a); ll_container.addView(textView); a++; } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(forSumReceiver); } }
public class MyIntentService extends IntentService { public MyIntentService() { //必須實現父類的構造方法 super("MyIntentService"); } @Override public void onCreate() { Log.i("TEST","onCreate()"); super.onCreate(); } @Override public void onStart(Intent intent, int startId) { Log.i("TEST","onStart()"); super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("TEST","onStartCommand()"); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { Log.i("TEST", "onBind()"); return super.onBind(intent); } @Override public void onDestroy() { Log.i("TEST","onDestroy()"); super.onDestroy(); } @Override protected void onHandleIntent(Intent intent) { Log.i("TEST","onHandleIntent():"+android.os.Process.myTid()); if (intent!=null){ String action=intent.getAction(); if(Constans.ACTION_FOR_SUM.equals(action)){ int a=intent.getIntExtra(Constans.A,0); int b=intent.getIntExtra(Constans.B,0); int result=a+b; Log.i("TEST","result: "+result); handleResult(a,result); } } } private void handleResult(int a,int result){ try{ //模擬計算耗時 Thread.sleep(3000); Intent intent=new Intent(Constans.ACTION_RESULT); intent.putExtra(Constans.RESULT,result); intent.putExtra(Constans.A,a); sendBroadcast(intent); }catch (InterruptedException e){ e.printStackTrace();; } } public static void startMyIntentService(Context context,int a,int b){ Intent intent=new Intent(context,MyIntentService.class); intent.setAction(Constans.ACTION_FOR_SUM); intent.putExtra(Constans.A,a); intent.putExtra(Constans.B,b); context.startService(intent); } }
07-08 10:18:51.579 com.troy.intentservicedemo I/TEST: MainActivity:30060 07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onCreate() 07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onStartCommand() 07-08 10:19:26.009 com.troy.intentservicedemo I/TEST: onStart() 07-08 10:19:26.039 com.troy.intentservicedemo I/TEST: onHandleIntent():30223 07-08 10:19:26.039 com.troy.intentservicedemo I/TEST: result: 23 07-08 10:19:29.100 com.troy.intentservicedemo I/TEST: onDestroy() 07-08 10:19:31.839 com.troy.intentservicedemo I/TEST: onCreate() 07-08 10:19:31.849 com.troy.intentservicedemo I/TEST: onStartCommand() 07-08 10:19:31.849 com.troy.intentservicedemo I/TEST: onStart() 07-08 10:19:31.869 com.troy.intentservicedemo I/TEST: onHandleIntent():30305 07-08 10:19:31.869 com.troy.intentservicedemo I/TEST: result: 52 07-08 10:19:34.899 com.troy.intentservicedemo I/TEST: onDestroy()
IntentService是Service的子類,擁有Service的所有生命周期方法;同時還有自己的ServiceHandler;
public abstract class IntentService extends Service { private volatile Looper mServiceLooper;//volatile關鍵字保證同步,保證可見性 private volatile ServiceHandler mServiceHandler; private String mName; private boolean mRedelivery; private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } } public IntentService(String name) {//構造方法 super(); mName = name; }
IntentService 實際上是Looper,Handler,Service 的集合體,他不僅有服務的功能,還有處理和循環消息的功能。
@Override public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
IntentService創建時就會創建Handler線程(HandlerThread)並且啟動,然後再得到當前線程的Looper對象來初始化IntentService的mServiceLooper,接著創建mServicehandler對象。
@Override public void onStart(Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }
當你啟動IntentService的時候,就會產生一條附帶startId和Intent的 Message並發送到MessageQueue中,接下來Looper發現MessageQueue中有Message的時候,就會停止Handler 處理消息。
@Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); }
接著調用 onHandleIntent((Intent)msg.obj),這是一個抽象的方法,其實就是我們要重寫實現的方法,我們可以在這個方法裡面處理我們的工作.當任務完成時就會調用stopSelf(msg.arg1)這個方法來結束指定的工作。
注意下:回調完成後回調用 stopSelf(msg.arg1),注意這個msg.arg1是個int值,相當於一個請求的唯一標識。每發送一個請求,會生成一個唯一的標識,然後將請求放入隊列,當全部執行完成(最後一個請求也就相當於getLastStartId == startId),或者當前發送的標識是最近發出的那一個(getLastStartId == startId),則會銷毀我們的Service.如果傳入的是-1則直接銷毀。
當所有的工作執行完後:就會執行onDestroy方法。
@Override public void onDestroy() { mServiceLooper.quit(); }
服務結束後調用這個方法 mServiceLooper.quit()使looper停下來。
1、 IntentService是一個基於消息的服務,每次啟動該服務並不是馬上處理你的工作,而是首先會創建對應的Looper,Handler並且在MessageQueue中添 加的附帶客戶Intent的Message對象, 當Looper發現有Message的時候接著得到Intent對象通過在 onHandleIntent((Intent)msg.obj)中調用你的處理程序. 處理完後即會停止自己的服務. 意思是Intent的生命周期跟你的 處理的任務是一致的. 所以這個類用下載任務中非常好,下載任務結束後服務自身就會結束退出。
2、IntentService是不適合用於bindService()這樣的啟動方式的。其次我們通過startService多次啟動Service時,相當於在MessageQueue中添加了多個任務,就可以實現多任務按照順序執行。
3、只有在onHandleIntent()方法中執行的代碼才是在工作線程中運行的。IntentService的停止不是因為在handleMessage() 中執行了stopSelf(msg.arg1);而是系統自己停止的。
NanoHttpd是個很強大的開源庫,僅僅用一個Java類,就實現了一個輕量級的 Web Server,可以非常方便地集成到Android應用中去,讓你的App支
Android開發人員都知道,原生的模擬器啟動比較慢,操作起來也不流暢,還會出現莫名的問題。當然很多人都會選擇直接使用android手機來開發,但是有時候需要在投
本文由碼農網 – 唐李川原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃! 上周一我非常開心。因為我被允許為一個曾經工作過的客戶開始開發一個
除了Android系統自帶的Button按鈕以外,還提供了帶圖標的按鈕ImageButton 要制作帶圖標的按鈕,首先要在布局文件中定義ImageButton,然