Android 多進程編程 15問15答!

ps:閱讀本文 須要對android 多進程編程有必定了解。html

1.Android中總共有幾種方式進行IPC?java

答:一共有兩種,一種是binder 還有一種是socket。Binder 你們用的比較多。Socket不多有人用,這裏給出一個利用Socket進行ipc通訊的例子。android

服務端代碼:編程

 1 package com.example.administrator.socketipcdemo;
 2 
 3 import android.app.Service;
 4 import android.content.Intent;
 5 import android.os.IBinder;
 6 import android.util.Log;
 7 
 8 import java.io.BufferedReader;
 9 import java.io.BufferedWriter;
10 import java.io.IOException;
11 import java.io.InputStreamReader;
12 import java.io.OutputStreamWriter;
13 import java.io.PrintWriter;
14 import java.net.ServerSocket;
15 import java.net.Socket;
16 
17 public class ServerService extends Service {
18 
19     public static final int SERVER_PORT_NUMBER = 5678;
20     private boolean mServiceDestroyed = false;
21 
22     @Override
23     public void onCreate() {
24         new Thread(new ServerRunnable()).start();
25         super.onCreate();
26     }
27 
28     @Override
29     public void onDestroy() {
30         mServiceDestroyed = true;
31         super.onDestroy();
32     }
33 
34     public ServerService() {
35     }
36 
37     @Override
38     public IBinder onBind(Intent intent) {
39         // TODO: Return the communication channel to the service.
40         throw new UnsupportedOperationException("Not yet implemented");
41     }
42 
43     //這個線程 用於監聽端口號
44     class ServerRunnable implements Runnable {
45         @Override
46         public void run() {
47 
48             ServerSocket serverSocket = null;
49             try {
50                 serverSocket = new ServerSocket(SERVER_PORT_NUMBER);
51             } catch (IOException e) {
52                 e.printStackTrace();
53             }
54             while (!mServiceDestroyed) {
55                 try {
56                     final Socket client = serverSocket.accept();
57                     new Thread() {
58                         @Override
59                         public void run() {
60                             try {
61                                 responseClientRequest(client);
62                             } catch (IOException e) {
63                                 e.printStackTrace();
64                             }
65                         }
66                     }.start();
67 
68                 } catch (IOException e) {
69                     e.printStackTrace();
70                 }
71             }
72         }
73     }
74 
75     private void responseClientRequest(Socket client) throws IOException {
76         BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
77         PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
78         while (!mServiceDestroyed) {
79             String str = in.readLine();
80             if (str == null) {
81                 break;
82             }
83             String reponseStr = "我是服務器端,我收到了來自客戶端的消息:" + str;
84             out.println(reponseStr);
85         }
86         out.close();
87         in.close();
88         client.close();
89     }
90 }
View Code

客戶端代碼:緩存

  1 package com.example.administrator.socketipcdemo;
  2 
  3 import android.content.Intent;
  4 import android.os.Bundle;
  5 import android.os.SystemClock;
  6 import android.support.design.widget.FloatingActionButton;
  7 import android.support.design.widget.Snackbar;
  8 import android.support.v7.app.AppCompatActivity;
  9 import android.support.v7.widget.Toolbar;
 10 import android.util.Log;
 11 import android.view.View;
 12 import android.view.Menu;
 13 import android.view.MenuItem;
 14 import android.widget.Button;
 15 import android.widget.EditText;
 16 import android.widget.TextView;
 17 import android.widget.Toast;
 18 
 19 import java.io.BufferedReader;
 20 import java.io.BufferedWriter;
 21 import java.io.IOException;
 22 import java.io.InputStreamReader;
 23 import java.io.OutputStreamWriter;
 24 import java.io.PrintWriter;
 25 import java.net.Socket;
 26 
 27 public class MainActivity extends AppCompatActivity {
 28 
 29     private Button bt, bt2;
 30     private TextView tv;
 31     private EditText et;
 32 
 33     private Socket socket;
 34     private PrintWriter mPrintWriter;
 35 
 36 
 37     @Override
 38     protected void onCreate(Bundle savedInstanceState) {
 39         super.onCreate(savedInstanceState);
 40         setContentView(R.layout.activity_main);
 41         Intent intent = new Intent(this, ServerService.class);
 42         startService(intent);
 43         tv = (TextView) findViewById(R.id.tv);
 44         et = (EditText) findViewById(R.id.et);
 45         bt = (Button) this.findViewById(R.id.bt);
 46         bt.setOnClickListener(new View.OnClickListener() {
 47             @Override
 48             public void onClick(View v) {
 49                 new Thread() {
 50                     @Override
 51                     public void run() {
 52                         tryToLinkServer();
 53                     }
 54                 }.start();
 55 
 56             }
 57         });
 58 
 59         bt2 = (Button) this.findViewById(R.id.bt2);
 60         bt2.setOnClickListener(new View.OnClickListener() {
 61             @Override
 62             public void onClick(View v) {
 63                 sendMessageToServer(et.getText().toString());
 64             }
 65         });
 66 
 67         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
 68         setSupportActionBar(toolbar);
 69 
 70         FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
 71         fab.setOnClickListener(new View.OnClickListener() {
 72             @Override
 73             public void onClick(View view) {
 74                 Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
 75                         .setAction("Action", null).show();
 76             }
 77         });
 78     }
 79 
 80     @Override
 81     protected void onDestroy() {
 82         if(socket!=null)
 83         {
 84             try {
 85                 socket.shutdownInput();
 86                 socket.close();
 87             } catch (IOException e) {
 88                 e.printStackTrace();
 89             }
 90         }
 91         super.onDestroy();
 92     }
 93 
 94     @Override
 95     public boolean onCreateOptionsMenu(Menu menu) {
 96         // Inflate the menu; this adds items to the action bar if it is present.
 97         getMenuInflater().inflate(R.menu.menu_main, menu);
 98         return true;
 99     }
100 
101     @Override
102     public boolean onOptionsItemSelected(MenuItem item) {
103         // Handle action bar item clicks here. The action bar will
104         // automatically handle clicks on the Home/Up button, so long
105         // as you specify a parent activity in AndroidManifest.xml.
106         int id = item.getItemId();
107 
108         //noinspection SimplifiableIfStatement
109         if (id == R.id.action_settings) {
110             return true;
111         }
112 
113         return super.onOptionsItemSelected(item);
114     }
115 
116     private void sendMessageToServer(final String str) {
117         if (mPrintWriter != null) {
118             mPrintWriter.println(str);
119         }
120     }
121 
122 
123     private void tryToLinkServer() {
124         while (socket == null) {
125             try {
126                 socket = new Socket("localhost", ServerService.SERVER_PORT_NUMBER);
127                 mPrintWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
128             } catch (IOException e) {
129                 //每次連不上就等待1秒再從新連
130                 SystemClock.sleep(1000);
131                 e.printStackTrace();
132             }
133         }
134         runOnUiThread(new Runnable() {
135             @Override
136             public void run() {
137                 Toast.makeText(MainActivity.this, "和服務器進程成功連接", Toast.LENGTH_SHORT).show();
138             }
139         });
140         try {
141             BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
142             while (!MainActivity.this.isFinishing()) {
143                 final String msg = br.readLine();
144                 runOnUiThread(new Runnable() {
145                     @Override
146                     public void run() {
147                         tv.setText(msg);
148                     }
149                 });
150             }
151             mPrintWriter.close();
152             br.close();
153             socket.close();
154         } catch (IOException e) {
155             e.printStackTrace();
156         }
157     }
158 
159 
160 }
View Code

最後看一下運行效果:安全

 

2.android:process 屬性值的書寫有什麼講究?服務器

答::remote 這種寫法 其實就等於 包名:remote 並且這種寫法 屬於當前app的私有進程, 其餘app 不能夠和這個進程跑在一塊兒的。網絡

若是是直接 把android:process 寫成字符串形式的話, 那這種進程就是全局進程了,誰均可以用。哪怕是其餘app 只要是shareUid同樣app

就能夠和這個進程跑在一塊兒。固然了,簽名也必須同樣!dom

 

3.多進程編程的時候 咱們須要注意哪些坑?

答:必定要記住 多進程的時候 實際上 一個進程就是一個虛擬機,因此 會引起以下幾個問題:

a:全部靜態變量和單例模式之類的 所有沒用了。由於你多進程麼,假設你的app代碼裏面 開啓了2個進程,同時你的代碼裏面 有一個靜態變量,這個時候注意 你的靜態變量雖然在代碼裏只有一份,

可是此時是2個進程在跑 ,有2個虛擬機,因此你這個靜態變量也是會變成兩份的!

b:SharedPreferences 會失去同步效果。由於sp這個東西 大家看下源碼就知道了,實際上他的底層就是個xml。。。而且android 對這個xml的讀寫本身弄了一套緩存,注意這個緩存是運行在內存中的,

因此你就知道 一旦多個進程的話,這個緩存就是多份了。。。。因此記住 不要在多進程裏面使用sp

c:Application 會建立屢次。這個大家打下log就知道了,因此若是大家application 有特殊處理的話 記得考慮下多進程的狀況。

上面3個是咱們須要注意的點,其實也很好理解,對於同一個app的 多個進程來講 ,他就等於 多個app 在運行,只不過這些app的uid和簽名都同樣!你想明白這點 就懂了android 多進程了。

 

4.android中有哪幾種序列化方式?分別要注意什麼?

答:兩種。Serializable和Parcelable

Serializable:這種方式 就是要注意serialVersionUID,通常ide 給你生成的值 都是根據你class的結構來作的,假設你在版本1.0.1 裏面 建立了class A,而且序列化了一個對象a 在sd卡里。

過了一段時間 你在1.0.2 版本里 把A的代碼 改了不少,此時ide 會把你的serialVersionUID 值也隨之改掉。那若是你在1.0.2版本里 還想反序列化這個對象a的話 就會出錯了。

因此serialVersionUID 就是一個記錄class 版本號的標示,咱們最好仍是把他寫死。。。。這樣不會影響咱們的客戶端。此外 transient 這個標記的變量也不會被序列化。

Parcelable:write方法就是序列化的時候 執行的方法 creator 就是反序列化的過程。Intent bundle bitmap 都實現了這個接口。List Map 也能夠序列化 提早是 元素是這個接口對象。

二者基本上是差很少的,只不過Parcelable效率更高,通常在內存中使用時 咱們用Parcelable,若是是 序列化到本地或者網絡 這種流裏的時候 咱們就用Serializable 由於比較方便。 

 

5.當遇到一個數據 沒法放在Bundle裏時,如何進行進程間通信?

答:假設咱們有一個需求,讓A進程 計算一個東西之後 把 結果 result 傳遞給B進程。可是這個result結果 沒有實現Parcelable 接口也沒法放在bundle裏。此時 該如何傳遞這個result到B?

其實可讓A進程 啓動B進程 的一個intentService。讓這個service 去計算出來這個結果result,這時候 咱們會發現 此時這個service和b進程 在一個進程裏。 result固然就隨便傳遞了。不須要ipc來傳遞

 

6.Messenger 使用時,要注意哪些,他的原理是什麼?

答:原理的話 其實看一下 源碼就知道了:

1 /**
2      * Create a Messenger from a raw IBinder, which had previously been
3      * retrieved with {@link #getBinder}.
4      * 
5      * @param target The IBinder this Messenger should communicate with.
6      */
7     public Messenger(IBinder target) {
8         mTarget = IMessenger.Stub.asInterface(target);
9     }

一看到這個代碼咱們就明白 原理就是AIDL麼。要注意的話 就是Messenger只能用於單向通訊,不能用於雙向的 。若是你要用雙向通訊而且還要用Messenger來完成的話  就必須用2個Messenger。

Messenger傳遞對象就是傳遞的Message對象。其中咱們注意了,在進程通訊的時候,Message裏的object 字段 只能傳遞 系統的parceable對象。也就是intent bitmap 這種系統本身實現的parceable接口對象。

若是是咱們本身寫的parceable 是沒法放在object裏面 用於進程通訊的,若是你要用,請放在bundle裏。此外Messenger 在內部 是串行處理請求的,大量消息 一塊兒發給服務端這種業務模型

最好就別用Messenger了。直接本身寫一個AIDL 最合適。

 

7.使用AIDL的時候 有哪些注意事項?

答:有下面幾個注意事項:

a:aidl文件裏不是全部數據類型均可以使用。只支持 基本數據類型,string,charSequence,List(只支持ArrayList,且裏面的元素都能被AIDL支持),Map(只支持hashMap,而且元素必須是AIDL支持的),Parcelable,AIDL本身。

b:自定義的parceable對象要在aidl中 import 進來。而且自定義的parceable 要在aidl裏 也額外聲明一下,具體的看我前面的那篇blog便可。

c:aidl 裏面只能寫方法 不能寫靜態常量。

 

8.in out inout 這三個參數 在aidl 到底有啥用,不寫有什麼危害麼?

答:據我觀察 你不寫其實沒什麼危害,可是你寫明白了 傳輸效率會增長。其實這3個參數很好理解,簡單創建一個方法模型:

假設你的aidl文件裏有一個方法  void addPerson(Person person),這方法一看 就是客戶端傳一個person 到服務端 因此這個地方參數就是in。

若是你有一個方法叫 void getList(List a) 你看這個方法 就是把服務端的list 傳遞給這個參數a的list 那你就把參數寫成out便可。

inout 就更好理解了,實際就是 void modifyList(List b),意思就是 先把b 這個list 傳遞給服務端,而後還要修改這個list。

 

9.CopyOnWriteArrayList 能夠在aidl中使用嗎?爲何?

答:可使用。

1 public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {

雖然看聲明 他並無實現Parceable這個接口。也不是ArrayList的子類,但實際上AIDL支持的是抽象的List,因此在底層的時候 Binder 會把CopyOnWriteArrayList 

轉換成ArrayList 傳遞給客戶端的。ConcurrentHashMap 也是同樣。

 

10.Android 進程通訊時候 能傳遞對象嗎?

答:嚴格意義上 是不能的,實際上binder 會把客戶端傳遞過來的對象 從新轉換爲一個新的對象 傳遞給服務端。對象的跨進程傳輸 本質上就是序列化和反序列化的過程。

 

11.RemoteCallBackList 幹嗎的?使用時注意哪些?

答:具體可看http://www.cnblogs.com/punkisnotdead/p/5158016.html。 實際上這個東西講明白了 就是用於 android中管理 跨進程listener接口的。

你想明白這個道理 就都懂了。並且他特別方便的是,客戶端進程終止之後 他能夠自動刪除listenr。使用注意點就是begin和finish要成對出現。就算你是遍歷listenrer操做

也要用這2個方法

 

12.aidl運行時的 線程模型?

答:http://www.cnblogs.com/punkisnotdead/p/5163464.html 這篇分析binder代碼的時候 已經講的很清楚了。這裏再總結一次。

client 調用 server的方法a,client自己是會掛起的, 會一直等待server的方法a的 執行結果。

同時這個方法a 是運行在binder線程池中,因此server的方法  能夠執行耗時操做。只不過 client調用的server方法時

注意不要在ui線程裏調用,否則會anr的。同時若是你的業務是 一個server 多種client ,那你的server端 方法 要支持同步,否則會數據錯亂的!

 

13.服務端 調用 客戶端listener 方法有什麼講究?

答:實際上 和12問題是同樣的,server 想調用 client的方法b,b也是會執行在 client所屬進程的 binder線程池內的。同時咱們也要避免 若是方法b執行時間很長,

記得server調用的時候 不要在主線程裏調用。此外咱們通常client 都是在activity裏,記得 listener調用的方法 若是涉及到ui,請用handler切換到ui線程來作。

 

14.如何作權限認證?

答:兩種方法,能夠在onBind裏 檢查權限,也能夠在server的onTransact裏驗證,驗證失敗返回false便可。後者方法更好 還能夠驗證uid pid等 能夠支持複雜的多進程業務模型,

尤爲是安全相關的。

 

15.一個aidl 就必須對應一個service嗎?多種aidl 是否是隻能多個service?

答:不是的,aidl 只不過是幫你書寫binder用的工具,你固然能夠只啓動一個service 可是對應多個binder。要知道 service 資源是有限的 假設你app複雜 10個業務 開啓10個service

那不是就亂套了。徹底能夠只開啓一個service 可是這一個service 能夠控制多種aidl 對應的binder,你要用哪一個 就取那個binder 便可。

下面給出實例。

首先看一下 代碼結構和運行效果,實際上就是一個加法binder 和一個乘法binder 只不過 這2個binder 都由一個service來控制而已。

 

 

而後來看一下加法和乘法的 aidl以及對應的binder 對象:

1 // IAddition.aidl
2 package com.example.administrator.bindermanager;
3 
4 // Declare any non-default types here with import statements
5 
6 interface IAddition {
7 
8     int add(int a,int b);
9 }
View Code
 1 package com.example.administrator.bindermanager;
 2 
 3 import android.os.RemoteException;
 4 
 5 /**
 6  * Created by Administrator on 2016/1/29.
 7  */
 8 public class AdditionImpl extends IAddition.Stub {
 9     @Override
10     public int add(int a, int b) throws RemoteException {
11         return a + b;
12     }
13 }
View Code
1 // IMultiplication.aidl
2 package com.example.administrator.bindermanager;
3 
4 // Declare any non-default types here with import statements
5 
6 interface IMultiplication {
7 
8     int multip(int a,int b);
9 }
View Code
 1 package com.example.administrator.bindermanager;
 2 
 3 import android.os.RemoteException;
 4 
 5 /**
 6  * Created by Administrator on 2016/1/29.
 7  */
 8 public class MultiplicationImpl extends IMultiplication.Stub {
 9     @Override
10     public int multip(int a, int b) throws RemoteException {
11         return a * b;
12     }
13 }
View Code

 

而後看看咱們最爲關鍵的binder manger 如何設計:

1 // IBinderManger.aidl
2 package com.example.administrator.bindermanager;
3 
4 // Declare any non-default types here with import statements
5 
6 interface IBinderManger {
7     IBinder queryBinder(int binderCode);
8 }
View Code
 1 package com.example.administrator.bindermanager;
 2 
 3 import android.os.IBinder;
 4 import android.os.RemoteException;
 5 import android.util.Log;
 6 
 7 /**
 8  * Created by Administrator on 2016/1/29.
 9  */
10 public class BinderMangerImpl extends IBinderManger.Stub {
11 
12     public BinderMangerImpl() {
13         super();
14     }
15 
16     @Override
17     public IBinder queryBinder(int binderCode) throws RemoteException {
18         IBinder binder = null;
19         switch (binderCode) {
20             case BinderManger.BINDER_ADDITION:
21                 binder = new AdditionImpl();
22                 break;
23             case BinderManger.BINDER_MULTIPLICATION:
24                 binder = new MultiplicationImpl();
25                 break;
26             default:
27                 break;
28         }
29         return binder;
30     }
31 }
View Code
 1 package com.example.administrator.bindermanager;
 2 
 3 import android.app.Service;
 4 import android.content.Intent;
 5 import android.os.Binder;
 6 import android.os.IBinder;
 7 import android.util.Log;
 8 
 9 public class BinderMangerService extends Service {
10 
11     private IBinder mBinderManger = new BinderMangerImpl();
12 
13     public BinderMangerService() {
14     }
15 
16     @Override
17     public IBinder onBind(Intent intent) {
18         return mBinderManger;
19     }
20 }
View Code
 1 package com.example.administrator.bindermanager;
 2 
 3 import android.content.ComponentName;
 4 import android.content.Context;
 5 import android.content.Intent;
 6 import android.content.ServiceConnection;
 7 import android.os.IBinder;
 8 import android.os.RemoteException;
 9 
10 /**
11  * Created by Administrator on 2016/1/29.
12  */
13 public class BinderManger {
14 
15     public static final int BINDER_ADDITION = 0;
16     public static final int BINDER_MULTIPLICATION = 1;
17     private Context mContext;
18     private IBinderManger mBinderManger;
19     private static BinderManger sInstance;
20 
21     private BinderManger(Context mContext) {
22         this.mContext = mContext.getApplicationContext();
23         connectBinderService();
24     }
25 
26     public static BinderManger getInstance(Context context) {
27         if (sInstance == null) {
28             sInstance = new BinderManger(context);
29         }
30         return sInstance;
31     }
32 
33 
34     private synchronized void connectBinderService() {
35         Intent service = new Intent(mContext, BinderMangerService.class);
36         mContext.bindService(service, mServiceConnection, Context.BIND_AUTO_CREATE);
37     }
38 
39     private ServiceConnection mServiceConnection = new ServiceConnection() {
40         @Override
41         public void onServiceConnected(ComponentName name, IBinder service) {
42             mBinderManger = IBinderManger.Stub.asInterface(service);
43         }
44 
45         @Override
46         public void onServiceDisconnected(ComponentName name) {
47 
48         }
49     };
50 
51     public IBinder queryBinder(int binderCode) throws RemoteException {
52         IBinder binder = null;
53         binder = mBinderManger.queryBinder(binderCode);
54         return binder;
55     }
56 }
View Code

最後看一下 咱們的clinet端:

  1 package com.example.administrator.bindermanager;
  2 
  3 import android.os.Bundle;
  4 import android.os.RemoteException;
  5 import android.support.design.widget.FloatingActionButton;
  6 import android.support.design.widget.Snackbar;
  7 import android.support.v7.app.AppCompatActivity;
  8 import android.support.v7.widget.Toolbar;
  9 import android.view.View;
 10 import android.view.Menu;
 11 import android.view.MenuItem;
 12 import android.widget.Button;
 13 import android.widget.EditText;
 14 import android.widget.TextView;
 15 
 16 import org.w3c.dom.Text;
 17 
 18 public class MainActivity extends AppCompatActivity {
 19 
 20     private Button bt, bt2, bt3;
 21     private EditText et1, et2;
 22     private TextView tv;
 23     private BinderManger binderManger;
 24 
 25     @Override
 26     protected void onCreate(Bundle savedInstanceState) {
 27         super.onCreate(savedInstanceState);
 28         setContentView(R.layout.activity_main);
 29         tv = (TextView) findViewById(R.id.tv2);
 30         et1 = (EditText) findViewById(R.id.et);
 31         et2 = (EditText) findViewById(R.id.et2);
 32         bt = (Button) this.findViewById(R.id.bt);
 33         bt.setOnClickListener(new View.OnClickListener() {
 34 
 35             @Override
 36             public void onClick(View v) {
 37                 binderManger = BinderManger.getInstance(MainActivity.this);
 38             }
 39         });
 40 
 41         bt2 = (Button) this.findViewById(R.id.bt2);
 42         bt2.setOnClickListener(new View.OnClickListener() {
 43 
 44             @Override
 45             public void onClick(View v) {
 46                 try {
 47                     final IMultiplication multiplicationImpl =
 48                             (IMultiplication) MultiplicationImpl.asInterface(binderManger.queryBinder(BinderManger.BINDER_MULTIPLICATION));
 49 
 50                     runOnUiThread(new Runnable() {
 51                         @Override
 52                         public void run() {
 53                             try {
 54                                 tv.setText(multiplicationImpl.multip(Integer.parseInt(et1.getText().toString()), Integer.parseInt(et2.getText().toString())) + "");
 55                             } catch (RemoteException e) {
 56                                 e.printStackTrace();
 57                             }
 58                         }
 59                     });
 60 
 61                 } catch (RemoteException e) {
 62                     e.printStackTrace();
 63                 }
 64             }
 65         });
 66 
 67         bt3 = (Button) this.findViewById(R.id.bt3);
 68         bt3.setOnClickListener(new View.OnClickListener() {
 69 
 70             @Override
 71             public void onClick(View v) {
 72                 try {
 73                     final IAddition additionImpl =
 74                             (IAddition) AdditionImpl.asInterface(binderManger.queryBinder(BinderManger.BINDER_ADDITION));
 75                     runOnUiThread(new Runnable() {
 76                         @Override
 77                         public void run() {
 78                             try {
 79                                 tv.setText(additionImpl.add(Integer.parseInt(et1.getText().toString()), Integer.parseInt(et2.getText().toString())) + "");
 80                             } catch (RemoteException e) {
 81                                 e.printStackTrace();
 82                             }
 83                         }
 84                     });
 85 
 86                 } catch (RemoteException e) {
 87                     e.printStackTrace();
 88                 }
 89             }
 90         });
 91 
 92 
 93         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
 94         setSupportActionBar(toolbar);
 95 
 96         FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
 97         fab.setOnClickListener(new View.OnClickListener() {
 98             @Override
 99             public void onClick(View view) {
100                 Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
101                         .setAction("Action", null).show();
102             }
103         });
104     }
105 
106     @Override
107     public boolean onCreateOptionsMenu(Menu menu) {
108         // Inflate the menu; this adds items to the action bar if it is present.
109         getMenuInflater().inflate(R.menu.menu_main, menu);
110         return true;
111     }
112 
113     @Override
114     public boolean onOptionsItemSelected(MenuItem item) {
115         // Handle action bar item clicks here. The action bar will
116         // automatically handle clicks on the Home/Up button, so long
117         // as you specify a parent activity in AndroidManifest.xml.
118         int id = item.getItemId();
119 
120         //noinspection SimplifiableIfStatement
121         if (id == R.id.action_settings) {
122             return true;
123         }
124 
125         return super.onOptionsItemSelected(item);
126     }
127 }
View Code
相關文章
相關標籤/搜索