亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android組件之服務(wù)的詳解

 更新時間:2021年08月30日 17:47:48   作者:Cristiano_san  
這篇文章主要詳細(xì)介紹了Android組件之一的服務(wù),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、服務(wù)的概念

1、服務(wù)是實(shí)現(xiàn)程序后臺運(yùn)行的解決方案,主要執(zhí)行那些不需要和用戶交互而且還要求長期運(yùn)行的任務(wù)

2、服務(wù)是依賴于創(chuàng)建服務(wù)時所在的應(yīng)用程序進(jìn)程而存在的,而不是運(yùn)行在一個獨(dú)立的進(jìn)程當(dāng)中

3、服務(wù)的后臺≠創(chuàng)建子線程,需要在服務(wù)的內(nèi)部手動創(chuàng)建子線程,并且在這里執(zhí)行具體的任務(wù),否則可能會出現(xiàn)主線程被堵塞的情況

二、Android的多線程編程

2.1 線程的基本用法

  • 線程聲明方式一:
	//定義方式
	class myThread extends Thread{
		  @Override
		  public void run(){
		  		//具體的處理邏輯
		  }
	}
	
	//啟動方式
	new myThread().start();
  • 線程聲明方式二:
	//定義方式
	class myThread implements Runnable{
		 @Override
		  public void run(){
		  		//具體的處理邏輯
		  }
	}
	
	//啟動方式
		myThread my = new myThread();
		new Thread(my).start();
  • 線程聲明方式三:
	new Thread(new Runnable() {
            @Override
            public void run() {

			}
	}).start();

2.2 在子線程中更新UI

更新方式一

利用runOnUiThread()方法,該方法可以要執(zhí)行的操作回調(diào)到主線程中進(jìn)行操作,使用方法:

以更新TextView為例:

	@Override
    protected void onCreate(Bundle savedInstanceState) {
        .....
        change.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        changeUI("next to meet you");
                    }
                }).start();
            }
        });
    }
    public void changeUI(String date){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                text.setText(date);
            }
        });
    }

1、我們在子線程中調(diào)用changeUI()方法,并將更改后的數(shù)據(jù)傳過去
2、在changeUI()方法中,調(diào)用runOnUiThread()方法將進(jìn)程調(diào)回到主線程中,然后調(diào)用setText()方法進(jìn)行更新UI操作

具體使用方法,博客:理解 Activity.runOnUiThread

更新方式二

利用Android自帶的異步消息處理機(jī)制

public class MainActivity extends AppCompatActivity {
    public static final int UPDATE_TEXT = 1;
    private TextView text;

    private Handler handler = new Handler(){
        public void handleMessage(Message msg){
            switch (msg.what){
                case UPDATE_TEXT:
                    //對UI進(jìn)行操作
                    text.setText("Nice to meet you");
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ....
        change.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message message = new Message();
                        message.what = UPDATE_TEXT;
                        handler.sendMessage(message);
                    }
                }).start();
            }
        });
    }
}

1、首先定義一個字段UPDATE_TEXT表示更新的具體動作
2、創(chuàng)建Handler的對象,并重寫父類的handleMessage()方法,在該方法中對Message進(jìn)行處理
3、判斷Message的what的值,進(jìn)行相應(yīng)的UI操作
4、回到子線程,首先獲取一個Message 的對象,對what字段賦值
5、調(diào)用Handler對象的sendMessage()將這個Message 發(fā)送出去
6、在Handler收到這個消息以后就會調(diào)用handleMessage()對消息進(jìn)行處理,且現(xiàn)在已經(jīng)是在主線程中處理不會出現(xiàn)問題

2.3 解析異步消息處理機(jī)制

1、處理機(jī)制組成:Message、Handler、MessageQueue、Looper

2、Message:

  • 1)作用:在線程之間傳遞信息
  • 2)可以在內(nèi)部攜帶少量信息,利用其字段,如what,arg1,rg2,obj字段存儲,用于在不同線程之間交換數(shù)據(jù)

3、Handler:

  • 1)作用:主要用于發(fā)送和處理消息
  • 2)發(fā)送消息使用Handler的sendMessage()方法
  • 3)發(fā)出的消息經(jīng)過處理以后,傳遞到Handler的handleMessage()方法中

4、MessageQueue:

  • 1)作用:主要用于存放所有通過Handler發(fā)送的消息。每個線程中只有一個MessageQueue對象

5、Looper:

  • 1)作用:每個線程中MessageQueue的管家
  • 2)在調(diào)用其loop()方法后,進(jìn)入無限循環(huán),在循環(huán)中每發(fā)現(xiàn)MessageQueue中存在一條消息就將其取出,傳遞到Handler的handleMessage()方法中進(jìn)行處理
  • 3)每個線程中只有一個Looper對象

6、整個異步流程:

在這里插入圖片描述

  • 1)首先主線程中創(chuàng)建一個Handler的對象,并重寫父類的handleMessage()方法
  • 2)在子線程要進(jìn)行UI操作時,創(chuàng)建一個Message對象,通過Handler的sendMessage()方法出去
  • 3)這條消息會被添加到MessageQueue隊(duì)列中等待
  • 4)Looper從MessageQueue中取出一條消息,傳遞到Handler的handleMessage()方法中進(jìn)行處理

2.4 使用AsyncTask

1、AsyncTask的實(shí)現(xiàn)原理是基于異步消息處理機(jī)制的
2、AsyncTask是一個抽象類,在子類繼承這個類時指定3個泛型參數(shù):

  • Params:在執(zhí)行AsyncTask時需傳入的參數(shù),可用于在后臺任務(wù)中使用
  • Progress:后臺任務(wù)執(zhí)行時,若需要在界面上顯示當(dāng)前進(jìn)度,這里就指定的泛型作為進(jìn)度單位
  • Result:當(dāng)任務(wù)執(zhí)行完畢,若需要對結(jié)果進(jìn)行返回,則使用這里指定的泛型作為返回值類型
  • 如:
public class DownloadTask extends AsyncTask<Void,Integer,Boolean> {
    ....
}

第一個泛型參數(shù)指定為Void,表示在執(zhí)行AsyncTask時不需要傳入?yún)?shù)給后臺任務(wù)
第二個參數(shù)指定為Integer,表示使用整型數(shù)據(jù)來作為進(jìn)度顯示單位
第三個參數(shù)指定為Boolean,表示用boolean類型數(shù)據(jù)來反饋執(zhí)行結(jié)果

3、在繼承后,還需重寫如下方法

  • onPreExecute() :在后臺任務(wù)開始執(zhí)行之前調(diào)用,用于進(jìn)行一些界面上的初始化操作,如顯示一個進(jìn)度條對話框等
  • doInBackground(Params… ) :該方法中所有的代碼都會在子線程中運(yùn)行。后臺任務(wù)一旦完成通過return語句將任務(wù)的執(zhí)行結(jié)果返回,若AsyncTask第三個參數(shù)指定為Void,則可以不返回任務(wù)執(zhí)行結(jié)果。若需要更新UI元素,則調(diào)用publishProgress(Progress…)方法來完成
  • onProgressUpdate(Progress… ):當(dāng)在后臺任務(wù)中調(diào)用publishProgress(Progress…)方法,該方法就會被調(diào)用,該方法所攜帶的參數(shù)就是在后臺任務(wù)中傳遞過來的,在這個方法中利用參數(shù)中的數(shù)值可以對UI進(jìn)行操作
  • onPostExecute(Result) :后臺任務(wù)執(zhí)行完畢并返回return語句進(jìn)行返回時,這個方法就會被調(diào)用,返回的數(shù)據(jù)作為參數(shù)會傳遞到此方法中,可以利用返回的數(shù)據(jù)來進(jìn)行一些UI操作,如提醒任務(wù)執(zhí)行的結(jié)果,或關(guān)閉進(jìn)度條對話框等具體框架:
		public class DownloadTask extends AsyncTask<Void,Integer,Boolean> {
		    @Override
		    protected void onPreExecute() {
		        progressDialog.show();//顯示進(jìn)度對話框
		    }
		
		    @Override
		    protected Boolean doInBackground(Void... voids) {//在該方法里執(zhí)行下載任務(wù)
		        try{
		            while(true){
		                int percent = doDownload();//虛構(gòu)一個方法,返回一個值表示下載進(jìn)度
		                publishProgress(percent);//調(diào)用publishProgress方法,并將進(jìn)度數(shù)值傳進(jìn)去
		                if(percent >= 100)
		                    break;
		            }
		        }catch (Exception e){
		            e.printStackTrace();
		        }
		        return true;
		    }
		
		    @Override
		    protected void onProgressUpdate(Integer... values) {//該方法所帶的參數(shù)就是publishProgress()方法的進(jìn)度數(shù)值
		        progressDialog.setMessage("Downloaded" + values[0] + "%");
		    }
		
		    @Override
		    protected void onPostExecute(Boolean aBoolean) {//后臺任務(wù)完成后該方法就會被調(diào)用
		        progressDialog.dismiss();//關(guān)閉進(jìn)度對話框
		        //提示下載結(jié)果
		        if (aBoolean){
		            Toast.makeText(context,"Succeeded",Toast.LENGTH_SHORT).show();
		        }else {
		            Toast.makeText(context,"Failed",Toast.LENGTH_SHORT).show();
		        }
		    }
		}

4、啟動方法:

	new DownloadTask().execute();

三、服務(wù)的基本用法

3.1 首先定義一個服務(wù)

在這里插入圖片描述

在上述界面中:Exported表示是否允許除了當(dāng)前程序之外的其他程序訪問這個服務(wù);Enabled表示是否啟動這個服務(wù)

3.2 MyService類里重寫幾個方法

	public class MyService extends Service {
	    public MyService() {
	    }
	    @Override
	    public IBinder onBind(Intent intent) {
	        // TODO: Return the communication channel to the service.
	        throw new UnsupportedOperationException("Not yet implemented");
	    }
	
	    @Override
	    public void onCreate() {
	        super.onCreate();
	    }//服務(wù)被創(chuàng)建時調(diào)用
	
	    @Override
	    public int onStartCommand(Intent intent, int flags, int startId) {
	        return super.onStartCommand(intent, flags, startId);
	    }//每次服務(wù)啟動時調(diào)用,若需要服務(wù)一旦啟動就立刻執(zhí)行某個動作,就可以將邏輯卸載這個方法里面
	
	    @Override
	    public void onDestroy() {
	        super.onDestroy();
	    }//服務(wù)被銷毀時調(diào)用
	}

1、onCreate()方法在服務(wù)被創(chuàng)建時調(diào)用
2、onStartCommand()方法在每次服務(wù)啟動時調(diào)用,若需要服務(wù)一旦啟動就立刻執(zhí)行某個動作,就可以將邏輯卸載這個方法里面
3、onDestroy()方法在服務(wù)被銷毀時調(diào)用
4、onCreate()方法在服務(wù)第一次創(chuàng)建時調(diào)用,onStartCommand()方法是在每次啟動服務(wù)時調(diào)用(若在一次服務(wù)中調(diào)用了onDestroy()方法,那么這個服務(wù)就無了,再點(diǎn)開始按鈕就會調(diào)用onCreate()方法)

3.3 在注冊文件中完成對服務(wù)的注冊

	<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	    package="com.example.testservices" >
	    <application
	        .....
	        <service
	            android:name=".MyService"
	            android:enabled="true"
	            android:exported="true" >
	        </service>
	        .....
	    </application>
	</manifest>

3.4 啟動和停止服務(wù)

首先要創(chuàng)建一個活動和兩個用于啟動服務(wù)的按鈕,創(chuàng)建完成后通過Intent實(shí)現(xiàn)活動和服務(wù)之間的“橋梁”搭建

		Button start = findViewById(R.id.start_service);
        Button stop = findViewById(R.id.stop_service);
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent startIntent = new Intent(MainActivity2.this,MyService.class);
                startService(startIntent);//啟動服務(wù)
            }
        });
        stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent stopIntent = new Intent(MainActivity2.this,MyService.class);
                stopService(stopIntent);//停止服務(wù)
            }
        });

關(guān)于讓服務(wù)停止,如果不點(diǎn)擊停止按鈕服務(wù)會一直處于運(yùn)行狀態(tài)??梢酝ㄟ^在MyService中指定的地方調(diào)用 stopSelf()方法 實(shí)現(xiàn)服務(wù)的自動停止

然后在MyService里定義一些日志

		public class MyService extends Service {
		    final static String TAG = "MyService";
		   	....
		    @Override
		    public void onCreate() {
		        super.onCreate();
		        Log.d(TAG,"onCreate executed");
		    }//服務(wù)被創(chuàng)建時調(diào)用
		
		    @Override
		    public int onStartCommand(Intent intent, int flags, int startId) {
		        Log.d(TAG,"onStartCommand executed");
		        return super.onStartCommand(intent, flags, startId);
		    }//每次服務(wù)啟動時調(diào)用,若需要服務(wù)一旦啟動就立刻執(zhí)行某個動作,就可以將邏輯卸載這個方法里面
		
		    @Override
		    public void onDestroy() {
		        super.onDestroy();
		        Log.d(TAG,"onDestroy executed");
		    }//服務(wù)被銷毀時調(diào)用
		}

運(yùn)行結(jié)果:

在這里插入圖片描述

3.5 活動和服務(wù)進(jìn)行通信

以下載功能為例:在服務(wù)中提供一個下載功能,在活動中決定何時開始下載以及隨時查看下載進(jìn)度

1、首先在MyService中創(chuàng)建一個Binder的子類內(nèi)部類,對下載功能進(jìn)行管理:

		 class DownloadBinder extends Binder{
		        public void startDownload(){
		            Log.d(TAG,"startDownload executed");
		        }//開始下載的模擬方法
		        public int getProgress(){
		            Log.d(TAG,"getProgress executed");
		            return 0;
		        }//查看下載進(jìn)度的模擬方法
		    }

2、然后同樣地,在MyService里獲取到DownloadBinder 的實(shí)例,并且通過 onBind()方法 返回這個實(shí)例(最關(guān)鍵的一步)

 	private DownloadBinder binder = new DownloadBinder();
	.....
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return binder;
    }

3、在活動中定義兩個按鈕,分別用于綁定服務(wù)和服務(wù)解綁

4、在活動中創(chuàng)建一個ServiceConnection的匿名類,并重寫onServiceConnected()、onServiceDisconnected()方法,這兩個方法會在活動與服務(wù)成功綁定和斷開時調(diào)用

public class MainActivity2 extends AppCompatActivity {
    private MyService.DownloadBinder binder;
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            binder = (MyService.DownloadBinder) iBinder;
            binder.startDownload();
            binder.getProgress();
            //在這里通過轉(zhuǎn)型獲取到Binder實(shí)例,通過這個實(shí)例,就可以在活動中根據(jù)具體的場景來調(diào)用DownloadBinder中任何public的方法
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        .....
    }
}

5、在按鈕事件里完成活動與服務(wù)之間的綁定和解綁

 		bind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent bindIntent = new Intent(MainActivity2.this,MyService.class);
                bindService(bindIntent,connection,BIND_AUTO_CREATE);//綁定服務(wù)
                //BIND_AUTO_CREATE是一個標(biāo)志位,該標(biāo)志位表示在活動和服務(wù)進(jìn)行綁定后自動創(chuàng)建服務(wù),即MyService里的onCreate()方法會得到執(zhí)行,onStartCommand()方法不會得到執(zhí)行
            }
        });
        unbind.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                unbindService(connection);//解除綁定
            }
        });

四、服務(wù)的生命周期

在這里插入圖片描述

在這里插入圖片描述

五、服務(wù)的更多技巧

5.1 使用前臺服務(wù)

1、前臺服務(wù)的作用:可以使服務(wù)一直保持運(yùn)行狀態(tài),而不會由于系統(tǒng)內(nèi)存不足的原因?qū)е卤换厥?br /> 2、跟普通服務(wù)的區(qū)別:一直有一個正在運(yùn)行的圖標(biāo)在系統(tǒng)的狀態(tài)欄顯示,下拉狀態(tài)欄后可以看到更詳細(xì)的信息
3、具體實(shí)現(xiàn):

public class MyService extends Service {
    .....
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG,"onCreate executed");
        Intent intent = new Intent(this,MainActivity2.class);
        PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);
        NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        Notification notification = new NotificationCompat.Builder(this,"YonC")
                .setContentTitle("This is content title")
                .setContentText("his is content text")
                .setWhen(System.currentTimeMillis())
                .setContentIntent(pi)
                .build();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("YonC", "YonC",NotificationManager.IMPORTANCE_HIGH);
            manager.createNotificationChannel(channel);
        }
        manager.notify(1,notification);
        startForeground(1,notification);
    }//服務(wù)被創(chuàng)建時調(diào)用
	.....
}

1、這里利用PendingIntent 和Notification 創(chuàng)建一個通知的形式創(chuàng)建了一個前臺活動
2、首先通過notify()方法將該通知顯現(xiàn)出來
3、然后調(diào)用startForeground()方法讓MyService變成一個前臺服務(wù),該方法接收兩個參數(shù),第一個參數(shù)是通知的id,
類似于notify()方法的第一個參數(shù);第二個參數(shù)為構(gòu)建出的Notification對象

4、注意還需要申請權(quán)限

	<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

5.2 服務(wù)中的多線程問題&IntentService

1、ANR:即Application Not Responding,直接在服務(wù)中處理一些耗時的邏輯就會出現(xiàn)此類情況
2、IntentService是服務(wù)的子類之一,在該類中的onHandleIntent()方法中的邏輯都是在子線程中執(zhí)行,因此可以將服務(wù)中一些耗時的邏輯都放在這個方法中從而避免ANR問題
3、具體實(shí)現(xiàn):

		public class MyIntentService extends IntentService {
		    public MyIntentService(){
		        super("MyIntentService");
		    }//這個無參的構(gòu)造函數(shù)和調(diào)用父類有參構(gòu)造函數(shù)是必須有的
		    @Override
		    protected void onHandleIntent(@Nullable Intent intent) {
		        //該方法里的邏輯都是在子線程中執(zhí)行的
		    }
		}
	 son.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity2.this,MyIntentService.class);
                startService(intent);
            }
        });

在按鈕注冊事件中引用Intent “建橋”,再調(diào)用startService()方法開啟服務(wù)

    <service android:name=".MyIntentService"/>

完成該服務(wù)的注冊

到此這篇關(guān)于Android組件之服務(wù)的詳解的文章就介紹到這了,更多相關(guān)Android組件服務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解析android res 運(yùn)行錯誤的問題

    解析android res 運(yùn)行錯誤的問題

    本篇文章是對android中res運(yùn)行錯誤的問題進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • PopupWindow自定義位置顯示的實(shí)現(xiàn)代碼

    PopupWindow自定義位置顯示的實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了PopupWindow自定義位置顯示,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 分享Android中pullToRefresh的使用心得

    分享Android中pullToRefresh的使用心得

    這篇文章主要介紹了分享Android中pullToRefresh的使用心得的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • Android中Canvas的常用方法總結(jié)

    Android中Canvas的常用方法總結(jié)

    在Android自定義View的時候,我們經(jīng)常需要繪制一些自己想要的效果。這里就需要使用Canvas對象。下面這篇文章將Canvas對象常用方法做個筆記,方便自己和大家以后使用的時候查閱,下面來一起看看吧。
    2016-09-09
  • Android路由框架ARouter的使用示例

    Android路由框架ARouter的使用示例

    組件化或者模塊化開發(fā)模式,已逐漸成為熱浪的形式,使用這些模式可以讓我們程序更容易的擴(kuò)展、更方便的維護(hù)、更快捷的同步開發(fā)與更簡單的單獨(dú)調(diào)試,而ARouter的出現(xiàn)就是讓組件間、模塊間是實(shí)現(xiàn)完全的獨(dú)立。ARouter主要解決組件間、模塊間的界面跳轉(zhuǎn)問題。
    2021-06-06
  • gradle中的properties文件詳解

    gradle中的properties文件詳解

    這篇文章主要介紹了gradle中的properties文件詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 務(wù)必掌握的Android十六進(jìn)制狀態(tài)管理最佳實(shí)踐

    務(wù)必掌握的Android十六進(jìn)制狀態(tài)管理最佳實(shí)踐

    這篇文章主要為大家介紹了務(wù)必掌握的Android十六進(jìn)制狀態(tài)管理最佳實(shí)踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 如何利用adb卸載手機(jī)預(yù)裝軟件(系統(tǒng)軟件)

    如何利用adb卸載手機(jī)預(yù)裝軟件(系統(tǒng)軟件)

    對于Android手機(jī)通常有很多不必要的預(yù)置軟件,但是又無法卸載,占用桌面有很難受,所以本次使用adb工具來實(shí)現(xiàn)從電腦命令來卸載或停用軟件,下面這篇文章主要給大家介紹了關(guān)于如何利用adb卸載手機(jī)預(yù)裝軟件(系統(tǒng)軟件)的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • Android生成條形碼和二維碼功能

    Android生成條形碼和二維碼功能

    隨著移動互聯(lián)網(wǎng)的普及以及智能終端設(shè)備的廣泛應(yīng)用,移動支付變得越來越便捷,通過掃描二維碼代替?zhèn)鹘y(tǒng)的刷卡行為。這篇文章給大家介紹Android生成條形碼和二維碼功能,需要的朋友參考下吧
    2019-10-10
  • Android 自定義閃屏頁廣告倒計時view效果

    Android 自定義閃屏頁廣告倒計時view效果

    這篇文章主要介紹了Android 自定義閃屏頁廣告倒計時view效果,需要的朋友可以參考下
    2017-05-05

最新評論