編輯:關於Android編程
android 的線程模型:當一個 android 的應用運行後,就會有一個 UI 的 main 線程啟動 , 這是一個非常重要的線程,它負責把事件分派到相應的控件,其中就包括屏幕繪圖事件,它同樣是用戶與 android 控件 交互的線程。比如,當你在屏幕上的 EditText 上輸入文字, UI 線程會把這個事件分發給剛輸入文字的 EditText ,緊接會向事件隊列發送一個更新 ( invalidate )請求。 UI 線程會把這個請求移出事件隊列並通知 EditText 在屏幕上重新繪制自身。
這種單線線程模型就會使得 android 的應用程序性能低下, 如果在這個單線程裡執行一些耗時的操作, 比如訪問數據庫, 或是從網絡端下載圖片, 就會會阻塞整個用戶界面。 比如如下操作:
[java]
Bitmap b = loadImageFromNetwork();
Bitmap b = loadImageFromNetwork(); 這個操作非常耗時, 在這種情況下你會發現 , 界面僵死在那裡並且 android 在系統 5 秒中後沒有反應,會顯示一個關閉或等待的錯誤。
也許我們可以使用一個新的 Thread 來解決它
[java]
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap( b );
}
}).start();
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap( b );
}
}).start(); 但這樣會發生一些很難察覺的錯誤, 因為我們知道 UI 線程不是線程安全的。當然有很多種方法來處理這個問題:
android 提供了幾種在其他線程中訪問 UI 線程的方法。
• Activity.runOnUiThread( Runnable )
• View.post( Runnable )
• View.postDelayed( Runnable, long )
• Hanlder
[java]
new Thread( new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post( new Runnable() {
mImageView.setImageBitmap( b );
});
}
}).start();
new Thread( new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post( new Runnable() {
mImageView.setImageBitmap( b );
});
}
}).start();這種方法比較繁瑣,同時當你需要實現一些很復雜的操作並需要頻繁地更新UI 時這會變得更糟糕。為了解決這個問題,android 提供了一個工具類:AsyncTask ,它使創建需要與用戶界面交互的長時間運行的任務變得更簡單。
就拿加載網絡圖片舉個例子:
[java]
ublic class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{
private ImageView gView ;
protected Bitmap doInBackground(ImageView... views) {
Bitmap bmp = null ;
ImageView view = views[0];
// 根據iconUrl獲取圖片並渲染,iconUrl的url放在了view的tag中。
if (view.getTag() != null) {
try {
URL url = new URL(view.getTag().toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream stream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(stream);
stream.close();
} catch (Exception e) {
Log.v("img", e.getMessage());
return null;
}
}
this.gView = view;
return bmp;
}
protected void onPostExecute(Bitmap bm) {
if (bm != null) {
this.gView.setImageBitmap(bm);
this.gView = null ;
}
}
}
在Activity中直接調用
if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){
img.setImageResource(R.drawable.icon_app);
img.setTag(imgpath);
try{
new CanvasImageTask().execute(img);
img.setDrawingCacheEnabled(true);
}catch (Exception e) {
Log.e("error", "RejectedExecutionException in content_img: " + imgpath);
ublic class CanvasImageTask extends AsyncTask<ImageView, Void, Bitmap>{
private ImageView gView ;
protected Bitmap doInBackground(ImageView... views) {
Bitmap bmp = null ;
ImageView view = views[0];
// 根據iconUrl獲取圖片並渲染,iconUrl的url放在了view的tag中。
if (view.getTag() != null) {
try {
URL url = new URL(view.getTag().toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream stream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(stream);
stream.close();
} catch (Exception e) {
Log.v("img", e.getMessage());
return null;
}
}
this.gView = view;
return bmp;
}
protected void onPostExecute(Bitmap bm) {
if (bm != null) {
this.gView.setImageBitmap(bm);
this.gView = null ;
}
}
}
在Activity中直接調用
if(!img.isDrawingCacheEnabled() || !holder.image.getTag().equals(imgpath)){
img.setImageResource(R.drawable.icon_app);
img.setTag(imgpath);
try{
new CanvasImageTask().execute(img);
img.setDrawingCacheEnabled(true);
}catch (Exception e) {
Log.e("error", "RejectedExecutionException in content_img: " + imgpath);這樣圖片加載使用異步線程便不會進行堵塞發生錯誤,我們還可以使用 callback 在圖片加載完後進行回調
[java]
public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{
private ImageView gView ;
protected Bitmap doInBackground(ImageView... views) {
Bitmap bmp = null ;
ImageView view = views[0];
// 根據iconUrl獲取圖片並渲染,iconUrl的url放在了view的tag中。
if (view.getTag() != null) {
try {
URL url = new URL(view.getTag().toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream stream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(stream);
stream.close();
} catch (Exception e) {
e.printStackTrace();
Log.v("img", e.getMessage());
Message msg = new Message();
msg.what = 0;
handleMessage(msg);
return null;
}
}
this.gView = view;
return bmp;
}
protected void onPostExecute(Bitmap bm) {
if (bm != null) {
this.gView.setImageBitmap(bm);
this.gView.setTag(bm);
this.gView = null ;
Message msg = new Message();
msg.what = 1;
handleMessage(msg);
}
}
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
}
}
public class CanvasImageTaskCall extends AsyncTask<ImageView, Void, Bitmap> implements Callback{
private ImageView gView ;
protected Bitmap doInBackground(ImageView... views) {
Bitmap bmp = null ;
ImageView view = views[0];
// 根據iconUrl獲取圖片並渲染,iconUrl的url放在了view的tag中。
if (view.getTag() != null) {
try {
URL url = new URL(view.getTag().toString());
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream stream = conn.getInputStream();
bmp = BitmapFactory.decodeStream(stream);
stream.close();
} catch (Exception e) {
e.printStackTrace();
Log.v("img", e.getMessage());
Message msg = new Message();
msg.what = 0;
handleMessage(msg);
return null;
}
}
this.gView = view;
return bmp;
}
protected void onPostExecute(Bitmap bm) {
if (bm != null) {
this.gView.setImageBitmap(bm);
this.gView.setTag(bm);
this.gView = null ;
Message msg = new Message();
msg.what = 1;
handleMessage(msg);
}
}
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
return false;
}
}在 Activity 中直接調用
[java]
new CanvasImageTaskCall(){
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 0:
Log.i("test", "圖片加載失敗");
break;
case 1:
Log.i("test", "圖片加載成功");
break;
default:
break;
}
saveButton.setTextColor(Color.WHITE);
saveButton.setClickable(true);
bitmap = (Bitmap) imageView.getTag();
return super.handleMessage(msg);
}
}.execute(img);
new CanvasImageTaskCall(){
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 0:
Log.i("test", "圖片加載失敗");
break;
case 1:
Log.i("test", "圖片加載成功");
break;
default:
break;
}
saveButton.setTextColor(Color.WHITE);
saveButton.setClickable(true);
bitmap = (Bitmap) imageView.getTag();
return super.handleMessage(msg);
}
}.execute(img);
如果我們在每個xml文件中都把相同的布局都重寫一遍,一個是代碼冗余,可讀性很差;另一個是修改起來比較麻煩,對後期的修改和維護非常不利
有時候我們需要在游戲或應用中用一些符合我們樣式的提示框(AlertDialog),以下是我在開發一個小游戲中總結出來的.希望對大家有用.先上效果圖:下面是用到的背景圖或按
自定義實現Android百度地圖的縮放圖標,需要自定義一個縮放控件,實現效果如下: 這裡的縮放效果,實現了點擊按鈕可以對地圖的放大縮小,通過手勢放大與縮小也控制縮放圖標
由於項目需要,今天學習了一下如何將程序裡的數據添加到本地的Excel表中。下面為學習筆記:先上效果圖:首先,需要導入jxl.jar包到libs文件夾內。然後創建Excel