繼續整理一下做 Android 開發過程中遇到的一些問題和技巧。
1. 4.0 或以上版本的 Android 不能在主線程中連網
Android 應用程式運行在一個 dalvik 虛擬機器進程中,當這個進程開始的時候會啟動一個主線程( MainThread ),在 Android 4.0 或以上的版本中,強制禁止在主線程執行耗時的網路操作,若需要進行網路操作,則需要另外開闢線程或使用 AsyncTask ,下面介紹的是另外開闢線程的方法。
| 代碼如下 |
複製代碼 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.single); new Thread(postLoad).start(); } Runnable postLoad = new Runnable(){ @Override public void run() { // TODO Auto-generated method stub // 在這裡執行連網操作 } }; |
但是,連網操作後一般都需要根據連網所得資料更新 UI ,這時又會產生一個新問題,主線程負責處理和 UI 相關的操作,因此主線程又被稱為 UI 線程。而 Android 採用 UI 單執行緒模式,只能在主線程中對 UI 元素進行操作,在非 UI 線程直接對 UI 進行了操作,則會報錯。
為瞭解決這個問題,則需要利用 Android 的訊息迴圈的機制實現線程間的通訊。即在非 UI 線程發送訊息到 UI 線程,讓 UI 線程來進行 UI 的操作。例如,可以利用 View 的 post 方法告知 UI 線程執行操作更新 UI 。
| 代碼如下 |
複製代碼 |
Runnable postLoad = new Runnable(){ @Override public void run() { // TODO Auto-generated method stub // 連網擷取資料 data TextView textShow = (TextView) findViewById(R.id.show); textShow.post(new Runnable() { @Override public void run() { // 該方法會在 ui 線程執行 textShow.setText(data); } }); } }; |
2. 檢測是否有網路
| 代碼如下 |
複製代碼 |
final ConnectivityManager mConnectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); // 檢查網路連接,如果無網路可用,就不需要進行連網操作等 NetworkInfo info = mConnectivity.getActiveNetworkInfo(); if (info != null ) { // 若有網路 // 判斷網路連接類型 int netType = info.getType(); int netSubtype = info.getSubtype(); if (netType == ConnectivityManager.TYPE_WIFI) { // 若為 WIFI } else if (netType == ConnectivityManager.TYPE_MOBILE && netSubtype == TelephonyManager.NETWORK_TYPE_UMTS ) { // 若為 3G } else { // 其他網路 } } else { // 若無網路 } |
3. 自訂 touch 建立左右划動檢測
| 代碼如下 |
複製代碼 |
// 定義手勢速度記錄器 private VelocityTracker velocityTracker; // 定義手勢動作兩點之間的距離要求 private static final int VELOCITYX = 900; private static final int VELOCITYY = 800; WebView postContent = (WebView) findViewById(R.id.postContent); postContent.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View arg0, MotionEvent arg1) { // TODO Auto-generated method stub switch(arg1.getAction()){ case MotionEvent.ACTION_DOWN: if(velocityTracker == null){ // 取得手勢在螢幕上的滑動速度 velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(arg1); } break; case MotionEvent.ACTION_MOVE: if(velocityTracker != null){ velocityTracker.addMovement(arg1); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_OUTSIDE: break; case MotionEvent.ACTION_UP: int velocityX = 0, velocityY = 0; if(velocityTracker != null){ velocityTracker.addMovement(arg1); velocityTracker.computeCurrentVelocity(1000); // 計算每秒滑動多少個像素 velocityX = (int) velocityTracker.getXVelocity(); // 最後計算檢索 X 速度 velocityY = (int) velocityTracker.getYVelocity(); // 最後計算檢索 Y 速度 } // 從右向左劃 if( velocityX < -VELOCITYX && velocityY < VELOCITYY && velocityY > -VELOCITYY ){ // 執行相應操作 return true; } else if( velocityX > VELOCITYX && velocityY < VELOCITYY && velocityY > -VELOCITYY ) { // 從左向右劃 // 執行相應操作 return true; } else { // 判斷若不是划動操作,則返回 false 使用 WebView 自身的 touch 處理 return false; } } return false; } }); |
在檢測過程中發現觸摸操作不完整(例如划動距離太少,或者誤觸螢幕),或是直接判斷出不是划動操作,必須返回 false ,使到組件自身的 touch 處理得以保留。