近期項目中,遇到一個問題,清單資料中的圖檔位址是一個需要下載下傳JS再解析的字段,之前的圖檔下載下傳是一個異步的過程,由一個隊列處理。
Android系統以不同尋常的方式處理多個應用程式的同時運作。來自于其它不同平台的開發者或許會對這樣的運作機制感到很奇怪。而了解Android多任務的運作,對于設計出可以良好運作的應用程式,以及與Android平台的其它部分進行無縫結合都具有重要意義。這篇文章說明了Android的多任務方式設計上的成因,它對應用程式運作産生的影響,還有你可以怎樣更好地利用Android的這一特性。
public class ImageTaskExecutor {
/** 存放任務的連結清單,first-in last-out */
private LinkedList<ImageTask> mTaskQueue = null;
/** 執行任務的線程 */
private ThreadUnit mThreadUnit = null;
/** 執行任務的間隔時間 */
public static final long WAIT_PERIOD = 50L;
private volatile boolean paused;
private final Object signal = new Object();
/**
* 添加新任務
*
* @param task
* @return 是否添加成功
*/
public synchronized boolean addNewTask(final ImageTask task) {
if (mThreadUnit == null) {
mThreadUnit = new ThreadUnit();
mTaskQueue = new LinkedList<ImageTask>();
new Thread(mThreadUnit).start();
}
return mTaskQueue.offer(task);
}
class ThreadUnit implements Runnable {
public boolean isRunning = false;
private ImageTask task = null;
@Override
public void run() {
try {
isRunning = true;
while (isRunning) {
while (mTaskQueue != null && mTaskQueue.isEmpty()) {
try {
Thread.sleep(WAIT_PERIOD);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized (signal) {
while (paused) { // pause point
signal.wait();
if (mTaskQueue != null && !mTaskQueue.isEmpty()) {
task = mTaskQueue.removeFirst(); // 取對外連結表中的最後一個任務
if (task != null) {
task.execute();
} // end while
} catch (Exception e) {
e.toString();
}
} // end run
* 中斷任務的執行
public void pauseTaskThread() {
setPaused();
private void setPaused() {
synchronized (signal) {
paused = true;
private void setUnpaused() {
paused = false;
signal.notify();
* 恢複任務的執行
public void resumeTaskThread(){
setUnpaused();
* 終止任務的執行
public void terminateTaskThread() {
if (mThreadUnit != null) {
mThreadUnit.isRunning = false;
if (mTaskQueue != null) {
mTaskQueue.clear();
mThreadUnit = null;
mTaskQueue = null;
}
現在清單中的圖檔資訊需要解析,如果再開一個隊列,頁面直接卡得不動了。。。
然後,這時候就考濾整個下載下傳JS然後再下載下傳圖檔這個過程需要使用同步操作了
後來發現,這個過程操作會比較長,頁面的開始出現第一項的圖檔閃跳
原來adapter裡面的getView 方法,被調用的過程中,contentview裡面的内容會被随機複用,然後就。。。
public void inflateTaobaoImage(final String jsonUrl, final View view,
final int error_bg_Id) {
if (jsonUrl == null || jsonUrl.equals("")) {
return;
String imgUrl = getImgUrl(jsonUrl);
if (!TextUtils.isEmpty(imgUrl)) {
final String originJsonUrl = (String) view.getTag(IMG_TAG);
if (TextUtils.equals(originJsonUrl, jsonUrl)) {
LogsPrinter.debugError(TAG, "inflateTaobaoImage in HashMap "
+ originJsonUrl + " " + view);
inflateImage(imgUrl, view, error_bg_Id);
} else {
mTaskExecutor.addNewTask(new ImageTask(jsonUrl) {
@Override
public void execute() {
String taobaoImgUrl = downloadUrlString(jsonUrl
+ "&callback=success_jsonpCallback");
final String imgUrl = getTaobaoImageUrl(taobaoImgUrl);
LogsPrinter.debugError("add map", imgUrl + " " + jsonUrl);
taobaoImgMap.add(imgUrl, jsonUrl);
final String originJsonUrl = (String) view.getTag(IMG_TAG);
if (TextUtils.equals(originJsonUrl, jsonUrl)) {
baseHandlers.post(new Runnable() {
@Override
public void run() {
inflateImage(imgUrl, view, error_bg_Id);
}
});
}
});
值得注意的一個問題是:
settag的值需要是一個固定的值。不然,有時候會出現加載多次的情況。。