(本地、可通信的、前臺、遠程)Service使用全面介紹


前言


目錄


目錄

1. Service分類

1.1 Service的類型


分類

1.2 特點


Service類型的詳細介紹

2.具體使用解析

2.1 本地Service

這是最普通、最常用的後臺服務Service。

2.1.1 使用步驟

  • 步驟1:新建子類繼承Service類

    需重寫父類的onCreate()、onStartCommand()、onDestroy()和onBind()方法

  • 步驟2:構建用於啟動Service的Intent對象
  • 步驟3:調用startService()啟動Service、調用stopService()停止服務
  • 步驟4:在AndroidManifest.xml裡註冊Service

2.1.2 實例Demo

接下來我將用一個實例Demo進行本地Service說明

建議先下載Demo再進行閱讀:(carson.ho的Github地址)Demo_for_Service

  • 步驟1:新建子類繼承Service類

    需重寫父類的onCreate()、onStartCommand()、onDestroy()和onBind()

MyService.java

public class MyService extends Service {

//啟動Service之後,就可以在onCreate()或onStartCommand()方法裡去執行一些具體的邏輯 //由於這裡作Demo用,所以只打印一些語句 @Override public void onCreate() { super.onCreate(); System.out.println("執行了onCreat()"); }

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">onStartCommand</span><span class="hljs-params">(Intent intent, <span class="hljs-keyword">int</span> flags, <span class="hljs-keyword">int</span> startId)</span> </span>{
    System.out.println(<span class="hljs-string">"執行了onStartCommand()"</span>);
    <span class="hljs-function"><span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.<span class="hljs-title">onStartCommand</span><span class="hljs-params">(intent, flags, startId)</span></span>;


}

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onDestroy</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">super</span>.onDestroy();
    System.out.println(<span class="hljs-string">"執行了onDestory()"</span>);
}

<span class="hljs-meta">@Nullable</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-function">IBinder <span class="hljs-title">onBind</span><span class="hljs-params">(Intent intent)</span> </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
}

}

  • 步驟2:在主佈局文件設置兩個Button分別用於啟動和停止Service
    activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="scut.carson_ho.demo_service.MainActivity">
<span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
    <span class="hljs-attr">android:layout_centerInParent</span>=<span class="hljs-string">"true"</span>
    <span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/startService"</span>
    <span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"wrap_content"</span>
    <span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span>
    <span class="hljs-attr">android:text</span>=<span class="hljs-string">"啟動服務"</span> /&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
    <span class="hljs-attr">android:layout_centerInParent</span>=<span class="hljs-string">"true"</span>
    <span class="hljs-attr">android:layout_below</span>=<span class="hljs-string">"@+id/startService"</span>
    <span class="hljs-attr">android:id</span>=<span class="hljs-string">"@+id/stopService"</span>
    <span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"wrap_content"</span>
    <span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"wrap_content"</span>
    <span class="hljs-attr">android:text</span>=<span class="hljs-string">"停止服務"</span> /&gt;</span>

</RelativeLayout>

  • 步驟3:構建Intent對象,並調用startService()啟動Service、stopService停止服務

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
<span class="hljs-keyword">private</span> Button startService;
<span class="hljs-keyword">private</span> Button stopService;

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> onCreate(Bundle savedInstanceState) {
    <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    startService = (Button) findViewById(R.id.startService);
    stopService = (Button) findViewById(R.id.stopService);

    startService.setOnClickListener(<span class="hljs-keyword">this</span>);
    startService.setOnClickListener(<span class="hljs-keyword">this</span>);
}

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onClick(View v) {
    <span class="hljs-keyword">switch</span> (v.getId()) {

        <span class="hljs-comment">//點擊啟動Service Button</span>
        <span class="hljs-keyword">case</span> R.id.<span class="hljs-string">startService:</span>
            <span class="hljs-comment">//構建啟動服務的Intent對象</span>
            Intent startIntent = <span class="hljs-keyword">new</span> Intent(<span class="hljs-keyword">this</span>, MyService.<span class="hljs-keyword">class</span>);
            <span class="hljs-comment">//調用startService()方法-傳入Intent對象,以此啟動服務</span>
            startService(startIntent);

        <span class="hljs-comment">//點擊停止Service Button</span>
        <span class="hljs-keyword">case</span> R.id.<span class="hljs-string">stopService:</span>
            <span class="hljs-comment">//構建停止服務的Intent對象</span>
            Intent stopIntent = <span class="hljs-keyword">new</span> Intent(<span class="hljs-keyword">this</span>, MyService.<span class="hljs-keyword">class</span>);
            <span class="hljs-comment">//調用stopService()方法-傳入Intent對象,以此停止服務</span>
            stopService(stopIntent);

    }
}

}

  • 步驟4:在AndroidManifest.xml裡註冊Service
    AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="scut.carson_ho.demo_service">
<span class="hljs-tag">&lt;<span class="hljs-name">application</span>
    <span class="hljs-attr">android:allowBackup</span>=<span class="hljs-string">"true"</span>
    <span class="hljs-attr">android:icon</span>=<span class="hljs-string">"@mipmap/ic_launcher"</span>
    <span class="hljs-attr">android:label</span>=<span class="hljs-string">"@string/app_name"</span>
    <span class="hljs-attr">android:supportsRtl</span>=<span class="hljs-string">"true"</span>
    <span class="hljs-attr">android:theme</span>=<span class="hljs-string">"@style/AppTheme"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">activity</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">".MainActivity"</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">intent-filter</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">action</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.intent.action.MAIN"</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">category</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.intent.category.LAUNCHER"</span> /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">intent-filter</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">activity</span>&gt;</span>

    //註冊Service服務
    <span class="hljs-tag">&lt;<span class="hljs-name">service</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">".MyService"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">service</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">application</span>&gt;</span>

</manifest>

Androidmanifest裡Service的常見屬性說明

屬性 說明 備註
android:name Service的類名
android:label Service的名字 若不設置,默認為Service類名
android:icon Service的圖標
android:permission 申明此Service的權限 有提供了該權限的應用才能控制或連接此服務
android:process 表示該服務是否在另一個進程中運行(遠程服務) 不設置默認為本地服務;remote則設置成遠程服務
android:enabled 系統默認啟動 true:Service 將會默認被系統啟動;不設置則默認為false
android:exported 該服務是否能夠被其他應用程序所控制或連接 不設置默認此項為 false

2.1.3 測試結果


測試結果.png

2.1.4 Demo地址

Carson.ho的Github地址:Demo_for_Service

2.2 可通信的服務Service

  • 上面介紹的Service是最基礎的,但只能單機使用,即無法與Activity通信
  • 接下來將在上面的基礎用法上,增設“與Activity通信”的功能,即使用綁定Service服務(Binder類、bindService()、onBind()、unbindService()、onUnbind())

2.2.1 實例Demo

接下來我將用一個實例Demo進行可通信的服務Service說明

建議先下載Demo再進行閱讀:(carson.ho的Github地址)Demo_for_Service

  • 步驟1:在新建子類繼承Service類,並新建一個子類繼承自Binder類、寫入與Activity關聯需要的方法、創建實例
public class MyService extends Service {
<span class="hljs-keyword">private</span> MyBinder mBinder = <span class="hljs-keyword">new</span> MyBinder();

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">super</span>.onCreate();
    System.out.println(<span class="hljs-string">"執行了onCreat()"</span>);
}

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">onStartCommand</span><span class="hljs-params">(Intent intent, <span class="hljs-keyword">int</span> flags, <span class="hljs-keyword">int</span> startId)</span> </span>{
    System.out.println(<span class="hljs-string">"執行了onStartCommand()"</span>);
    <span class="hljs-function"><span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.<span class="hljs-title">onStartCommand</span><span class="hljs-params">(intent, flags, startId)</span></span>;


}

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onDestroy</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">super</span>.onDestroy();
    System.out.println(<span class="hljs-string">"執行了onDestory()"</span>);
}

<span class="hljs-meta">@Nullable</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-function">IBinder <span class="hljs-title">onBind</span><span class="hljs-params">(Intent intent)</span> </span>{
    System.out.println(<span class="hljs-string">"執行了onBind()"</span>);
    <span class="hljs-comment">//返回實例</span>
    <span class="hljs-keyword">return</span> mBinder;
}


<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">onUnbind</span><span class="hljs-params">(Intent intent)</span> </span>{
    System.out.println(<span class="hljs-string">"執行了onUnbind()"</span>);
    <span class="hljs-function"><span class="hljs-keyword">return</span> <span class="hljs-keyword">super</span>.<span class="hljs-title">onUnbind</span><span class="hljs-params">(intent)</span></span>;
}

<span class="hljs-comment">//新建一個子類繼承自Binder類</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyBinder</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Binder</span> </span>{

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">service_connect_Activity</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Service關聯了Activity,並在Activity執行了Service的方法"</span>);

    }
}

}

  • 步驟2:在主佈局文件再設置兩個Button分別用於綁定和解綁Service
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="scut.carson_ho.demo_service.MainActivity">
&lt;Button
    android:layout_centerInParent=<span class="hljs-string">"true"</span>
    android:<span class="hljs-built_in">id</span>=<span class="hljs-string">"@+id/startService"</span>
    android:layout_width=<span class="hljs-string">"wrap_content"</span>
    android:layout_height=<span class="hljs-string">"wrap_content"</span>
    android:<span class="hljs-built_in">text</span>=<span class="hljs-string">"啟動服務"</span> /&gt;

&lt;Button
    android:layout_centerInParent=<span class="hljs-string">"true"</span>
    android:layout_below=<span class="hljs-string">"@+id/startService"</span>
    android:<span class="hljs-built_in">id</span>=<span class="hljs-string">"@+id/stopService"</span>
    android:layout_width=<span class="hljs-string">"wrap_content"</span>
    android:layout_height=<span class="hljs-string">"wrap_content"</span>
    android:<span class="hljs-built_in">text</span>=<span class="hljs-string">"停止服務"</span> /&gt;

&lt;Button
    android:layout_centerInParent=<span class="hljs-string">"true"</span>
    android:layout_below=<span class="hljs-string">"@id/stopService"</span>
    android:<span class="hljs-built_in">id</span>=<span class="hljs-string">"@+id/bindService"</span>
    android:layout_width=<span class="hljs-string">"wrap_content"</span>
    android:layout_height=<span class="hljs-string">"wrap_content"</span>
    android:<span class="hljs-built_in">text</span>=<span class="hljs-string">"綁定服務"</span> /&gt;

&lt;Button
    android:layout_centerInParent=<span class="hljs-string">"true"</span>
    android:layout_below=<span class="hljs-string">"@id/bindService"</span>
    android:<span class="hljs-built_in">id</span>=<span class="hljs-string">"@+id/unbindService"</span>
    android:layout_width=<span class="hljs-string">"wrap_content"</span>
    android:layout_height=<span class="hljs-string">"wrap_content"</span>
    android:<span class="hljs-built_in">text</span>=<span class="hljs-string">"解綁服務"</span>
    /&gt;

</RelativeLayout>

  • 步驟3:在Activity通過調用MyBinder類中的public方法來實現Activity與Service的聯繫

    即實現了Activity指揮Service幹什麼Service就去幹什麼的功能

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
<span class="hljs-keyword">private</span> Button startService;
<span class="hljs-keyword">private</span> Button stopService;
<span class="hljs-keyword">private</span> Button bindService;
<span class="hljs-keyword">private</span> Button unbindService;

<span class="hljs-keyword">private</span> MyService.MyBinder myBinder;


<span class="hljs-comment">//創建ServiceConnection的匿名類</span>
<span class="hljs-keyword">private</span> ServiceConnection connection = <span class="hljs-keyword">new</span> ServiceConnection() {

    <span class="hljs-comment">//重寫onServiceConnected()方法和onServiceDisconnected()方法</span>
    <span class="hljs-comment">//在Activity與Service建立關聯和解除關聯的時候調用</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onServiceDisconnected(ComponentName name) {
    }

    <span class="hljs-comment">//在Activity與Service解除關聯的時候調用</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onServiceConnected(ComponentName name, IBinder service) {
        <span class="hljs-comment">//實例化Service的內部類myBinder</span>
        <span class="hljs-comment">//通過向下轉型得到了MyBinder的實例</span>
        myBinder = (MyService.MyBinder) service;
        <span class="hljs-comment">//在Activity調用Service類的方法</span>
        myBinder.service_connect_Activity();
    }
};

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> onCreate(Bundle savedInstanceState) {
    <span class="hljs-keyword">super</span>.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    startService = (Button) findViewById(R.id.startService);
    stopService = (Button) findViewById(R.id.stopService);

    startService.setOnClickListener(<span class="hljs-keyword">this</span>);
    stopService.setOnClickListener(<span class="hljs-keyword">this</span>);

    bindService = (Button) findViewById(R.id.bindService);
    unbindService = (Button) findViewById(R.id.unbindService);

    bindService.setOnClickListener(<span class="hljs-keyword">this</span>);
    unbindService.setOnClickListener(<span class="hljs-keyword">this</span>);

}

<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> onClick(View v) {
    <span class="hljs-keyword">switch</span> (v.getId()) {

        <span class="hljs-comment">//點擊啟動Service</span>
        <span class="hljs-keyword">case</span> R.id.<span class="hljs-string">startService:</span>
            <span class="hljs-comment">//構建啟動服務的Intent對象</span>
            Intent startIntent = <span class="hljs-keyword">new</span> Intent(<span class="hljs-keyword">this</span>, MyService.<span class="hljs-keyword">class</span>);
            <span class="hljs-comment">//調用startService()方法-傳入Intent對象,以此啟動服務</span>
            startService(startIntent);
            <span class="hljs-keyword">break</span>;

        <span class="hljs-comment">//點擊停止Service</span>
        <span class="hljs-keyword">case</span> R.id.<span class="hljs-string">stopService:</span>
            <span class="hljs-comment">//構建停止服務的Intent對象</span>
            Intent stopIntent = <span class="hljs-keyword">new</span> Intent(<span class="hljs-keyword">this</span>, MyService.<span class="hljs-keyword">class</span>);
            <span class="hljs-comment">//調用stopService()方法-傳入Intent對象,以此停止服務</span>
            stopService(stopIntent);
            <span class="hljs-keyword">break</span>;

        <span class="hljs-comment">//點擊綁定Service</span>
        <span class="hljs-keyword">case</span> R.id.<span class="hljs-string">bindService:</span>
            <span class="hljs-comment">//構建綁定服務的Intent對象</span>
            Intent bindIntent = <span class="hljs-keyword">new</span> Intent(<span class="hljs-keyword">this</span>, MyService.<span class="hljs-keyword">class</span>);
            <span class="hljs-comment">//調用bindService()方法,以此停止服務</span>

            bindService(bindIntent,connection,BIND_AUTO_CREATE);
            <span class="hljs-comment">//參數說明</span>
            <span class="hljs-comment">//第一個參數:Intent對象</span>
            <span class="hljs-comment">//第二個參數:上面創建的Serviceconnection實例</span>
            <span class="hljs-comment">//第三個參數:標誌位</span>
            <span class="hljs-comment">//這裡傳入BIND_AUTO_CREATE表示在Activity和Service建立關聯後自動創建Service</span>
            <span class="hljs-comment">//這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行</span>
            <span class="hljs-keyword">break</span>;

        <span class="hljs-comment">//點擊解綁Service</span>
        <span class="hljs-keyword">case</span> R.id.<span class="hljs-string">unbindService:</span>
            <span class="hljs-comment">//調用unbindService()解綁服務</span>
            <span class="hljs-comment">//參數是上面創建的Serviceconnection實例</span>
            unbindService(connection);
            <span class="hljs-keyword">break</span>;
default: break;
    }
}

}

2.2.2 測試結果


測試結果11.png

2.2.3 Demo

carson.ho的Github地址:Demo_for_Service

2.3 前臺Service

前臺Service和後臺Service(普通)最大的區別就在於:

  • 前臺Service在下拉通知欄有顯示通知(如下圖),但後臺Service沒有;

TT9$TN8IK1SAPDT%~0IRLS2.png
  • 前臺Service優先級較高,不會由於系統內存不足而被回收;後臺Service優先級較低,當系統出現內存不足情況時,很有可能會被回收

2.3.1 具體使用

用法很簡單,只需要在原有的Service類對onCreate()方法進行稍微修改即可,如下圖:

@Override
    public void onCreate() {
        super.onCreate();
        System.out.println("執行了onCreat()");
    <span class="hljs-comment">//添加下列代碼將後臺Service變成前臺Service</span>
    <span class="hljs-comment">//構建"點擊通知後打開MainActivity"的Intent對象</span>
    Intent notificationIntent = <span class="hljs-keyword">new</span> Intent(<span class="hljs-keyword">this</span>,MainActivity.<span class="hljs-keyword">class</span>);
    PendingIntent pendingIntent = PendingIntent.getActivity(<span class="hljs-keyword">this</span>,<span class="hljs-number">0</span>,notificationIntent,<span class="hljs-number">0</span>);

    <span class="hljs-comment">//新建Builer對象</span>
    Notification.Builder builer = <span class="hljs-keyword">new</span> Notification.Builder(<span class="hljs-keyword">this</span>);
    builer.setContentTitle(<span class="hljs-string">"前臺服務通知的標題"</span>);<span class="hljs-comment">//設置通知的標題</span>
    builer.setContentText(<span class="hljs-string">"前臺服務通知的內容"</span>);<span class="hljs-comment">//設置通知的內容</span>
    builer.setSmallIcon(R.mipmap.ic_launcher);<span class="hljs-comment">//設置通知的圖標</span>
    builer.setContentIntent(pendingIntent);<span class="hljs-comment">//設置點擊通知後的操作</span>

    Notification notification = builer.getNotification();<span class="hljs-comment">//將Builder對象轉變成普通的notification</span>
    startForeground(<span class="hljs-number">1</span>, notification);<span class="hljs-comment">//讓Service變成前臺Service,並在系統的狀態欄顯示出來</span>

}</code></pre>

2.3.2 測試結果

運行後,當點擊Start Service或Bind Service按鈕,Service就會以前臺Service的模式啟動(通知欄上有通知),如下圖


點擊啟動服務

2.4 遠程Service

具體請看我寫的另外一篇文章:Android:遠程服務Service(含AIDL & IPC講解)

3. 使用場景

  • 通過上述描述,你應該對Service類型及其使用非常瞭解;
  • 那麼,我們該什麼時候用哪種類型的Service呢?
  • 各種Service的使用場景請看下圖:

    使用場景

4. 總結


請點贊!因為你們的贊同/鼓勵是我寫作的最大動力!

相關文章閱讀
Android開發:最全面、最易懂的Android屏幕適配解決方案
Android開發:Handler異步通信機制全面解析(包含Looper、Message Queue)
Android開發:最全面、最易懂的Webview詳解
Android開發:JSON簡介及最全面解析方法!
Android開發:頂部Tab導航欄實現(TabLayout+ViewPager+Fragment)
Android開發:底部Tab菜單欄實現(FragmentTabHost+ViewPager)


歡迎關注Carson_Ho的簡書!

不定期分享關於安卓開發的乾貨,追求短、平、快,但卻不缺深度


    </div>

书籍推荐