編輯:Android編程入門
一、Android四大組件
1. Activity
生命周期:

2. Service
生命周期:

Service的生命周期長,沒有用戶界面,可以用來開發監控程序。
Service有兩種調用方式:
通過Context.startService()調用Service,當調用者關閉時,Service不會關閉,只用通過Context.stopService()才能關閉。
通過Context.bindService()調用Service,當調用者關閉時,Service也會關閉,關閉Service需要使用Context.unbindService()
3. Broadcast Receiver
Broadcast Receiver的生命周期只有十幾秒,所以不能在onReceive()中做耗時操作,否則會報ANR。也不能開子線程,因為可能子線程還沒運行完Broadcast Receiver就結束了。應該通過發送Intent給Service來處理。
動態注冊廣播接收器會隨著注冊的Activity關閉後關閉;靜態的廣播接收器即便app關閉,只要設備是開啟的,接收到廣播後仍能夠觸發。
4. Content Provider
二、Android 異步
1. Handler負責線程間通信
Handler處於構建它的主線程中,可以在子線程中通過post(Runnalbe)或者sendMessage(msg)來通知主線程更新UI。
Runnable: 執行handler.post(Runnalble),Handler將Runnable放入MessageQueue中,一旦從MessageQueue中取出,Runnable可以自動運行它的Run方法來進行主線程的UI更新。
主要方法:
boolean post(Runnable r) :從消息隊列中取出runnable後立即執行
boolean postAtTime(Runnable r, long uptimeMillis):從消息隊列中取出runnable後,指定時間執行
boolean postDelayed(Runnable r, long delayMillis):從消息隊列中取出runnable後,延遲一定時間執行
void removeCallbacks(Runnable r):從消息隊列中刪除runnable
Message: 執行handler.sendMessage()或者msg.sendToTarget(),Handler會將msg放入MessageQueue中,不過msg不能自動執行,需要重寫Handler的handleMessage方法,通過獲取msg中的信息進行UI更新。可以用setData(Bundle),其中Bundle可以通過putParcelable(String key, Parcelable value)和putSerializable(String key, Serializable value)傳遞對象。Message是一個final類不能繼承。有四個參數arg1,arg2,obj,what。
主要方法:
Message obtainMessage:從消息池中獲取一個msg
boolean sendMessage:發送一個消息到消息隊列,從消息隊列中取出後立即執行
boolean sendMessageDelayed:發送一個消息到消息隊列,從消息隊列中取出後延遲執行
boolean removeMessage:從消息隊列中移除一個未響應到消息
Handler用法,開一個子線程,然後在Handler.post(Runnable)的run方法裡面更新UI
public class MainActivity extends Activity {
ProgressDialog progressDialog;
Handler handler;
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.load_pic);
tv = (TextView) findViewById(R.id.tv);
progressDialog = new ProgressDialog(this);
progressDialog.setTitle("提示");
progressDialog.setMessage("正在加載,請稍後...");
progressDialog.setCancelable(false);
handler = new Handler();
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
System.out.println("執行完耗時操作");
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
@Override
public void run() {
tv.setText("執行完畢");
progressDialog.dismiss();
}
});
}
}).start();
}
});
}
}
Message用法
寫法1 message.obtain()不傳參數,需要調用handler.sendMessage(msg)發送msg
public class MainActivity extends Activity {
ProgressDialog progressDialog;
Handler handler;
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.load_pic);
tv = (TextView) findViewById(R.id.tv);
progressDialog = new ProgressDialog(this);
progressDialog.setTitle("提示");
progressDialog.setMessage("正在加載,請稍後...");
progressDialog.setCancelable(false);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
tv.setText(bundle.getString("tv"));
progressDialog.dismiss();
}
};
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
System.out.println("執行完耗時操作");
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("tv", "執行完畢");
msg.setData(bundle);
handler.sendMessage(msg);
}
}).start();
}
});
}
}
寫法2 Message.obtain(handler)傳一個handler參數,這樣可以直接調用msg.sendToTarget()方法,因為在message內部有一個Handler屬性的Target,相當於給target賦值為Handler。
public class MainActivity extends Activity {
ProgressDialog progressDialog;
Handler handler;
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.load_pic);
tv = (TextView) findViewById(R.id.tv);
progressDialog = new ProgressDialog(this);
progressDialog.setTitle("提示");
progressDialog.setMessage("正在加載,請稍後...");
progressDialog.setCancelable(false);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
tv.setText(bundle.getString("tv"));
progressDialog.dismiss();
}
};
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressDialog.show();
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
System.out.println("執行完耗時操作");
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = Message.obtain(handler);
Bundle bundle = new Bundle();
bundle.putString("tv", "執行完畢");
msg.setData(bundle);
msg.sendToTarget();
}
}).start();
}
});
}
}
2. AsyncTask類
簡單單一的異步操作
主要方法:
1. onPreExecute():由UI線程調用,異步操作開始執行之前調用
2. doInBackground():後台線程執行,處理耗時操作
3. onProgressUpdate():更新UI線程,在doInBackground中調用publicProgress()即可進行執行此方法
4. onPostExecute():UI線程調用,doInBackground()執行完之後調用
三、Android跨進程通信
利用四大組件實現:
1. Activity可以啟動其他進程的Activity
在調用者Activity中使用Intent來啟動被調用Activity,在被調用Activity中需要在AndroidManifest裡面配置該Activity的action和data,action表示被調用Activity的字符串ID,data表示被調用Activity的訪問協議Uri比如ok://abc。調用者Activity使用Intent(被調用Activity.Action, 被調用Activity.Uri)來啟動其他進程中的Activity。被調用Activity中getIntent().getData()獲得整體Uri, getIntent().getData().getHost()獲取Uri主體也就是ok://後面的abc,可以借助intent發送數據。當然如果在被調用Activity中setResult可以返回給調用者Activity數據,也就是數據通信可以是雙向的。
//調用者Activity裡面實現
Intent intent = new Intent("com.wwwsealss.action.another", Uri.parse("ok://go and fight!"));
intent.putExtra("value", "Hello world!");
startActivity(intent);
finish();
//被調用者AndroidManifest裡面注冊
<activity android:name=".Main2Activity" >
<intent-filter>
<action android:name="com.wwwsealss.action.another" />
<data android:scheme="ok" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
//被調用者Activity裡面實現
if (getIntent().getData() != null) {
//獲取Uri主體部分和intent中傳遞的數據
tv.setText(getIntent().getData().getHost() + getIntent().getStringExtra("value"));
}
2. Content Provider向其他應用共享數據,並且允許其他應用對數據的增刪改查
3. BroadCast 一個應用作為電台發送廣播,其他應用作為收音機接收廣播,但不能和電台進行通信,只能被動接收。
//通過intent發送廣播,需要加Action
Intent intent = new Intent("com.wwwsealss.receivebroadcast");
intent.putExtra("value", "Hello World!");
sendBroadcast(intent);
//注冊廣播接收器
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
String get = intent.getStringExtra("value");
Toast.makeText(context, get, Toast.LENGTH_SHORT).show();
Intent it = new Intent(context, MainActivity.class);
//如果沒有傳入Activity的上下文需要加個標志
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(it);
}
}
//在AndroidManifest中注冊Receiver
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="com.wwwsealss.receivebroadcast" />
</intent-filter>
</receiver>
4. AIDL是進程間通信的服務,首先需要在服務端創建AIDL文件(是一個接口,裡面的抽象方法就是共享給客戶端的),編譯後會生成對應的java文件。然後定義一個service,在其中完成AIDL接口的實現類(實現其內部的抽象方法),然後重寫service的onbind方法,讓其返回該AIDL實現類的實例化對象,這樣一來就完成了服務端。然後將AIDL文件放到客戶端工程中,注意AIDL所在文件的包名必須和服務端中的包名一致,然後定義serviceConnecton用於在綁定服務端後獲取其onbind方法返回的AIDL實現類的實例化對象(共享對象)。
//創建AIDL文件
interface IMyAidlInterface {
String getValue();
}
//定義服務端
public class MyService extends Service {
//實現AIDL接口中的方法
public class MyAidlInterface extends IMyAidlInterface.Stub {
@Override
public String getValue() throws RemoteException {
return "從AIDL服務獲取的值";
}
}
public MyService() {
}
//綁定該服務後返回AIDL接口的實現類的實例
@Override
public IBinder onBind(Intent intent) {
return new MyAidlInterface();
}
}
//在客戶端中實現
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通過intent Action綁定服務端
bindService(new Intent("com.example.administrator.findjob.IMyAidlInterface"), serviceConnection, Context.BIND_AUTO_CREATE);
}
});
//定義AIDL接口用於獲取發送過來的接口實現類
private IMyAidlInterface myAidlInterface = null;
//建立一個服務連接對象用於獲取服務端onbind返回值
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//獲取AIDL接口實現類對象
myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
//調用AIDL接口實現類對象中的方法
try {
Toast.makeText(MainActivity.this, myAidlInterface.getValue(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
三、Android自定義控件
三、Android系統框架
1. Linux Kernel 內核層
2. Hardware Abstraction Layer 硬件抽象層
3. Libraries and Runtime 系統運行庫層
4. Application Framework 應用程序框架層
5. Application 應用程序層
android中的所謂觀察者模式
生活中我們常認定某些人很有才,但什麼是有才呢?明朝的王守仁曾這樣解釋:才,是所謂天理,應用到物上,便成了才。凡事凡物,只要
Android添加按鈕事件的5種方法
第一種:匿名內部類作為事件監聽器類 大部分時候,事件處理器都沒有什麼利用價值(可利用代碼通常都被抽象成了業務邏輯方法),因此大部分事件監聽器只是臨時使用一次,所
Android學習筆記之短信驗證碼的獲取和讀取
PS:最近很多事情都拖拖拉拉的..都什麼辦事效率啊!!! 還得吐槽一下移動運營商,驗證碼超過五次的時候,直接把我的手機號封閉.真是受夠了. 學習筆記:1.And
Android 拍照或者從相冊獲取圖片的實現
我們常常會用到上傳頭像,或者發帖子的時候選擇本地圖片上傳的功能.這個很常見今天因為app的需求我研究了下.現在分享下.其實不論是通過拍照還是從相冊選取都會用到Intent