1. 程式人生 > >Android中,關於service的啟動兩種方式描述不正確的是

Android中,關於service的啟動兩種方式描述不正確的是

    

碰到群友問的一個問題,說:關於service的啟動兩種方式描述不正確的是(如圖)? 當時看到這個問題有點糾結,糾結內容如下:

A 選項沒有疑問,官網就是這麼說的

B選項就是我所糾結的地方,這個呼叫者如果退出了,那麼如果在onDestroy()中呼叫了unbindService 方法的話,那麼服務是終止的,這個是可以肯定的;但是如果沒有呼叫unbindService()方法的情況下,服務會終止嗎?(下面我對這個疑問做了實驗)

C選項也沒有疑問,官網就是這麼說的(雖然onStart()方法已經被  onStartCommand()取代,但是 onStartCommand()方法依然會呼叫onStart()方法),所以說也算是正確的。

    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
    }

D選項明顯是錯誤的,錯誤的地方最後一句,用stopService() 方法是結束不了用bindService()方法啟動的服務的(下面我會順道給予證實)。

我寫了個一個簡單的測試程式:如下:

package com.example.servicestest;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends ActionBarActivity {
	private TestService bindService = null;

	private Button mbtn, mBtn2;
	private Timer mTimer;
	private ActivityManager myAM;
	List<RunningServiceInfo> myList;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mBtn2 = (Button) findViewById(R.id.button2);
		mBtn2.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent intent = new Intent(MainActivity.this, TestService.class);
				//intent.putExtra("from", "ActivityA");
				bindService(intent, conn, BIND_AUTO_CREATE);

				Log.d("TestServiceMain", "StartService -- onclick");
			}
		});

		mbtn = (Button) findViewById(R.id.button1);
		mbtn.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				Intent intent = new Intent(MainActivity.this, TestService.class);
				MainActivity.this.stopService(intent);
				Log.d("TestServiceMain", "StopService -- onclick");
			}
		});
		if (mTimer == null) {
			mTimer = new Timer();
		}

		mTimer.schedule(new TimerTask() {

			@Override
			public void run() {
				// TODO Auto-generated method stub

				myAM = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
				myList = myAM.getRunningServices(Integer.MAX_VALUE);
				if (myList.size() <= 0) {
					Log.d("TestServiceMain", "runing  nothing ");
				}
				for (RunningServiceInfo service : myList) {
					if ("com.example.servicestest.TestService".equals(service.service.getClassName())) {
						Log.d("TestServiceMain", "runing !!!!!!!!!!!!!!!! " + service.service.getClassName());
					}
				}
				Log.d("TestServiceMain", "runing runing ");
			}
		}, 1000, 1000);
	}

	private ServiceConnection conn = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			TestService.LocalBind binder = (TestService.LocalBind) service;
			bindService = binder.getService();
		}

		//client 和service連線意外丟失時,會呼叫該方法  
		@Override
		public void onServiceDisconnected(ComponentName name) {
			bindService = null;

		}
	};

	protected void onDestroy() {
		Log.d("TestServiceMain", "MainActivity onDestroy()");
		unbindService(conn);
		Log.d("TestServiceMain", "MainActivity unbindService()");
		super.onDestroy();
	};
}


service

package com.example.servicestest;

import java.util.Timer;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class TestService extends Service {
	private final String TAG = "TestService";
	private LocalBind localBind = new LocalBind();
	private Timer mTimer;

	public class LocalBind extends Binder {
		public TestService getService() {
			return TestService.this;
		}
	}

	private final IBinder mBinder = new LocalBind();

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub  
		super.onCreate();
		Log.i(TAG, "onCreate~~~~~~~~~~");

	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(TAG, "onBind~~~~~~~~~~~~");
		return mBinder;
	}

	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);
		Log.i(TAG, "onStart~~~~~~~~~~~~");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub  
		Log.i(TAG, "onStartCommand~~~~~~~~~~~~");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub  
		Log.i(TAG, "onUnbind~~~~~~~~~~~~~~~~");
		return super.onUnbind(intent);
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub  
		super.onDestroy();
		Log.i(TAG, "onDestroy~~~~~~~~~~~");
	}

}

那麼先證實B選項的第一種情況:

在onDestroy()中呼叫了unbindService 方法的話,那麼服務是終止的。

日誌如下:

10-31 10:40:35.316: D/TestServiceMain(24971): runing runing 
10-31 10:40:36.321: D/TestServiceMain(24971): runing runing 
10-31 10:40:36.866: D/TestServiceMain(24971): StartService -- onclick
10-31 10:40:36.866: I/TestService(24971): onCreate~~~~~~~~~~
10-31 10:40:36.866: I/TestService(24971): onBind~~~~~~~~~~~~
10-31 10:40:37.316: D/TestServiceMain(24971): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:40:37.316: D/TestServiceMain(24971): runing runing 
10-31 10:40:38.316: D/TestServiceMain(24971): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:40:38.316: D/TestServiceMain(24971): runing runing 
10-31 10:40:39.316: D/TestServiceMain(24971): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:40:39.316: D/TestServiceMain(24971): runing runing 
10-31 10:40:40.316: D/TestServiceMain(24971): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:40:40.316: D/TestServiceMain(24971): runing runing 
10-31 10:40:41.321: D/TestServiceMain(24971): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:40:41.321: D/TestServiceMain(24971): runing runing 
10-31 10:40:42.321: D/TestServiceMain(24971): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:40:42.321: D/TestServiceMain(24971): runing runing 
10-31 10:40:42.611: D/TestServiceMain(24971): MainActivity onDestroy()
10-31 10:40:42.626: D/TestServiceMain(24971): MainActivity unbindService()
10-31 10:40:42.641: I/TestService(24971): onUnbind~~~~~~~~~~~~~~~~
10-31 10:40:42.641: I/TestService(24971): onDestroy~~~~~~~~~~~
10-31 10:40:43.316: D/TestServiceMain(24971): runing runing 

那麼再證實B選項第二種情況,但是如果沒有呼叫unbindService()方法的情況下,服務會終止嗎?(把 unbindService(conn); 註釋掉)日誌如下:
10-31 10:44:55.551: D/TestServiceMain(26043): runing runing 
10-31 10:44:56.551: D/TestServiceMain(26043): runing runing 
10-31 10:44:57.386: D/TestServiceMain(26043): StartService -- onclick
10-31 10:44:57.386: I/TestService(26043): onCreate~~~~~~~~~~
10-31 10:44:57.386: I/TestService(26043): onBind~~~~~~~~~~~~
10-31 10:44:57.561: D/TestServiceMain(26043): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:44:57.561: D/TestServiceMain(26043): runing runing 
10-31 10:44:58.566: D/TestServiceMain(26043): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:44:58.566: D/TestServiceMain(26043): runing runing 
10-31 10:44:59.561: D/TestServiceMain(26043): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:44:59.561: D/TestServiceMain(26043): runing runing 
10-31 10:45:00.556: D/TestServiceMain(26043): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:45:00.556: D/TestServiceMain(26043): runing runing 
10-31 10:45:01.571: D/TestServiceMain(26043): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:45:01.571: D/TestServiceMain(26043): runing runing 
10-31 10:45:02.326: D/TestServiceMain(26043): MainActivity onDestroy()
10-31 10:45:02.341: E/ActivityThread(26043): Activity com.example.servicestest.MainActivity has leaked ServiceConnection [email protected] that was originally bound here
10-31 10:45:02.341: E/ActivityThread(26043): android.app.ServiceConnectionLeaked: Activity com.example.servicestest.MainActivity has leaked ServiceConnection [email protected] that was originally bound here
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:983)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:877)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1959)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.app.ContextImpl.bindService(ContextImpl.java:1942)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.content.ContextWrapper.bindService(ContextWrapper.java:529)
10-31 10:45:02.341: E/ActivityThread(26043): 	at com.example.servicestest.MainActivity$2.onClick(MainActivity.java:40)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.view.View.performClick(View.java:4654)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.view.View$PerformClick.run(View.java:19438)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.os.Handler.handleCallback(Handler.java:733)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.os.Handler.dispatchMessage(Handler.java:95)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.os.Looper.loop(Looper.java:146)
10-31 10:45:02.341: E/ActivityThread(26043): 	at android.app.ActivityThread.main(ActivityThread.java:5602)
10-31 10:45:02.341: E/ActivityThread(26043): 	at java.lang.reflect.Method.invokeNative(Native Method)
10-31 10:45:02.341: E/ActivityThread(26043): 	at java.lang.reflect.Method.invoke(Method.java:515)
10-31 10:45:02.341: E/ActivityThread(26043): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
10-31 10:45:02.341: E/ActivityThread(26043): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
10-31 10:45:02.341: E/ActivityThread(26043): 	at dalvik.system.NativeStart.main(Native Method)
10-31 10:45:02.346: I/TestService(26043): onUnbind~~~~~~~~~~~~~~~~
10-31 10:45:02.346: I/TestService(26043): onDestroy~~~~~~~~~~~
10-31 10:45:02.556: D/TestServiceMain(26043): runing runing 
10-31 10:45:03.556: D/TestServiceMain(26043): runing runing 
10-31 10:45:04.561: D/TestServiceMain(26043): runing runing 

此種情況會給出一個異常,就是因為沒有呼叫unbindService()造成的,但是服務確實結束了。so~ 選項B證實是正確的。

那麼順道證實下選項D。

10-31 10:48:46.376: D/TestServiceMain(26752): runing runing 
10-31 10:48:47.366: D/TestServiceMain(26752): runing runing 
10-31 10:48:48.381: D/TestServiceMain(26752): runing runing 
10-31 10:48:49.361: D/TestServiceMain(26752): runing runing 
10-31 10:48:49.841: D/TestServiceMain(26752): StartService -- onclick
10-31 10:48:49.846: I/TestService(26752): onCreate~~~~~~~~~~
10-31 10:48:49.846: I/TestService(26752): onBind~~~~~~~~~~~~
10-31 10:48:50.361: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:50.366: D/TestServiceMain(26752): runing runing 
10-31 10:48:51.361: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:51.361: D/TestServiceMain(26752): runing runing 
10-31 10:48:52.376: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:52.376: D/TestServiceMain(26752): runing runing 
10-31 10:48:53.376: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:53.376: D/TestServiceMain(26752): runing runing 
10-31 10:48:54.381: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:54.381: D/TestServiceMain(26752): runing runing 
10-31 10:48:54.696: D/TestServiceMain(26752): StopService -- onclick
10-31 10:48:55.361: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:55.361: D/TestServiceMain(26752): runing runing 
10-31 10:48:56.361: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:56.361: D/TestServiceMain(26752): runing runing 
10-31 10:48:57.091: D/TestServiceMain(26752): StopService -- onclick
10-31 10:48:57.316: D/TestServiceMain(26752): StopService -- onclick
10-31 10:48:57.361: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:57.366: D/TestServiceMain(26752): runing runing 
10-31 10:48:57.531: D/TestServiceMain(26752): StopService -- onclick
10-31 10:48:57.701: D/TestServiceMain(26752): StopService -- onclick
10-31 10:48:58.376: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:58.376: D/TestServiceMain(26752): runing runing 
10-31 10:48:59.361: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:48:59.361: D/TestServiceMain(26752): runing runing 
10-31 10:49:00.376: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:49:00.376: D/TestServiceMain(26752): runing runing 
10-31 10:49:01.366: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:49:01.366: D/TestServiceMain(26752): runing runing 
10-31 10:49:02.361: D/TestServiceMain(26752): runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService
10-31 10:49:02.361: D/TestServiceMain(26752): runing runing 

如日誌:先呼叫了onCreate()——————》 onBind()   但是呼叫stopService()方法並不能終止服務。

所以這道題的答案是D。

重點備註:1、基於本例,判斷服務在不在執行是根據日誌:

runing !!!!!!!!!!!!!!!! com.example.servicestest.TestService

來判斷的。

2、Timer 脫離主執行緒(就是說應用退出後),也會繼續執行的。 所以避免錯誤的實驗,比如:把 Timer 放到service 中,讓他重複列印一條語句,那麼就算service 退出了,依然會有日誌輸出。

相關推薦

Android關於service啟動方式描述正確的是

     碰到群友問的一個問題,說:關於service的啟動兩種方式描述不正確的是(如圖)? 當時看到這個問題有點糾結,糾結內容如下: A 選項沒有疑問,官網就是這麼說的 B選項就是我所糾結的地方,這個呼叫者如果退出了,那麼如果在onDestroy()中呼叫了unbin

Android開發Service啟動方式的坑

和大家熟悉的Activity元件一樣,service也是Android應用開程式發中常用的元件,它和acitivy一樣也有自己的生命週期,不同的是service是執行在後臺的,沒有同用戶直接互動的介面。  service的是有兩種啟動方式: 第一種是通過startserv

Android小知識-剖析Retrofit網路請求的方式

本平臺的文章更新會有延遲,大家可以關注微信公眾號-顧林海,包括年底前會更新kotlin由淺入深系列教程,目前計劃在微信公眾號進行首發,如果大家想獲取最新教程,請關注微信公眾號,謝謝! 在上一節《Android小知識-剖析Retrofit中ServiceMethod相關引數以及建立過程》介紹了動態代

android開啟另外的app方式內建到自己本身的app重新開啟app

android開啟另外的app兩種方式,內建到自己本身的app空間,重新開啟app空間, 目錄 1、內建到自己本身的app空間, 被開啟的app的activity的主配置檔案的程式碼編寫、 <activity android:n

Android開發單元測試的方式

Android開發中單元測試的兩種方式 一位優秀的程式設計師也同樣不能保證自己的程式沒有bug,因此編寫合適的測試程式是完全有必要的,這樣也會降低程式在後期出現各種奇奇怪怪bug的可能,降低維護成本,未雨綢繆將bug扼殺在搖籃之中。 看到網上有很多依舊用寫java單元測試的

Android: Android Studio簽名打包的方式(zz)

信息 rda pan 相同 prop .cn 一個 一次 ack 註:給我們自己開發的app簽名,就代表著我自己的版權,以後要進行升級,也必須要使用相同的簽名才行。簽名就代表著自己的身份(即keystore),多個app可以使用同一個簽名。如果不知道簽名是啥意思,請自行百度

javascript教程系列40:DOM操作樣式的方式

AS color 單位 css 註意 pan col ntb javascrip 1 DOM中操作樣式的兩種方式 1 通過元素的style屬性 註意: 通過style屬性設置樣式時,css中要寫單位的屬性,在js代碼中也要加單位 //html <div id="bo

Android以JSONOject和GSON方式解析json

length pre ray oid 字符 CA clas img name json文件如下: 將獲取到的json數據轉化為String形式 OkHttpClient client = new OkHttpClient(); R

操作系統編程語言分類執行python方式變量內存管理定義變量的三個特征

什麽 height 取代 沒有 一個 Coding 開發 軟件 簡單 操作系統 1、什麽是操作系統 操作系統位於計算機硬件與應用軟件之間 是一個協調、管理、控制計算機硬件資源與軟件資源的控制程序2、為何要有操作系統? 1、控制硬件 2、把對硬件的復雜

C#Post請求的方式發送參數鏈和Body的

連接 png ets return div 參數 try 發現 create POST請求 有兩種方式 一種是組裝key=value這種參數對的方式 一種是直接把一個字符串發送過去 作為body的方式 我們在postman中可以看到 sfdsafd sdfsdfds

關於H5頁面生成圖片的方式

ima 前端 不能 圖片 項目 自定義 dom對象 技術分享 ron 前言: 我們在做項目過程中,經常會遇到自定義生成一張圖片並可以長按保存。長按保存圖片在微信等瀏覽器中默認就有,那麽對於生成圖片的有哪些方式呢? 方法一: 利用canvas繪制圖形,然後生成圖片 代碼如下:

testNGdataprovider使用的方式

pro ret urn expect highlight 參數化 sdn esp tin testNG的參數化測試有兩種方式:xml和dataprovider.個人更喜歡dataprovider,因為我喜歡把測試數據放在數據庫裏。 一.返回類型是Iterator<Ob

Android專案開源到JCenter方式

前言 開發中,或多或少都會用到無私的程式猿分享的開源專案,Androidstudio中使用開源也很方便 例如家喻戶曉的Rxjava,只需要一句話 compile 'io.reactivex:rxjava:1.1.6',就可以新增到專案中,時間久了,是不是自己也想試試開源一下自己的成果

mybatis批量插入的方式(高效插入)

一、mybiats foreach標籤 <insert id="insertBatch" parameterType="List"> INSERT INTO TStudent(name,age) <foreach collection="list" item="item" in

OL4新增圖示的方式的比較

前言:在ol中我們也可以新增一些圖示在地圖上,用於展示效果,較早期的版本OL提供一個overlay覆蓋物的方式,在OL3和OL4中這種用法不太多了,一個主要的原因它是通過HTML的方式的新增到地圖上,這種方式有一個很大的問題就是偏移,隨著你放大或者縮小可以看到圖示的位置明顯偏

AndroidonTouch與onClick監聽的完全解析

之前專案中做一個豎直方向的ViewPager效果(詳見我的另一篇博文),這幾天做了幾個改動,突然發現我設定的OnTouchListener對觸控事件的監聽突然不起作用了,琢磨了半天覺得問題就出在onTouch的返回值true還是false上,後來自己測試的時候發現不光與這個有關,與OnClickLi

SpringBoot使用AMQ的方式二(Java配置、註解方式

                                       使用@JmsListener註解方式 1. 工程目錄                                                                       

iText G (Android)PDF文字定位書寫方式介紹

閒言少敘,直接進入話題(相關基礎知識不瞭解,請使用百度之類惡補),有不當之處,請高人批准指正。。 方法一(絕對定位),參考形如: PdfContentByte pdfContentByte = pdfWriter.getDirectContent(); Base

vue引入echarts的方式

全域性引入 1. main.js中配置 import echarts from 'echarts' //引入echarts Vue.prototype.$echarts = echarts //引入元件 2. echarts在vue中的引用 <div id="

獲取IOC容器的bean的方式(id和class)的區別

// ClassPathXmlApplicationContext: 是 ApplicationContext的實現類,從類路徑下來載入配置檔案 ApplicationContext ctx=new ClassPathXmlApplicationContext("a