關(guān)于多任務(wù)下載問題
Android系統(tǒng)以不同尋常的方式處理多個(gè)應(yīng)用程序的同時(shí)運(yùn)行。來自于其它不同平臺的開發(fā)者或許會對這樣的運(yùn)行機(jī)制感到很奇怪。而理解Android多任務(wù)的運(yùn)行,對于設(shè)計(jì)出可以良好運(yùn)行的應(yīng)用程序,以及與Android平臺的其它部分進(jìn)行無縫結(jié)合都具有重要意義。這篇文章說明了Android的多任務(wù)方式設(shè)計(jì)上的成因,它對應(yīng)用程序運(yùn)行產(chǎn)生的影響,還有你可以怎樣更好地利用Android的這一特性。
近期項(xiàng)目中,遇到一個(gè)問題,列表數(shù)據(jù)中的圖片地址是一個(gè)需要下載JS再解析的字段,之前的圖片下載是一個(gè)異步的過程,由一個(gè)隊(duì)列處理。
- public class ImageTaskExecutor {
- /** 存放任務(wù)的鏈表,first-in last-out */
- private LinkedList<ImageTask> mTaskQueue = null;
- /** 執(zhí)行任務(wù)的線程 */
- private ThreadUnit mThreadUnit = null;
- /** 執(zhí)行任務(wù)的間隔時(shí)間 */
- public static final long WAIT_PERIOD = 50L;
- private volatile boolean paused;
- private final Object signal = new Object();
- /**
- * 添加新任務(wù)
- *
- * @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(); // 取出鏈表中的最后一個(gè)任務(wù)
- if (task != null) {
- task.execute();
- }
- }
- } // end while
- } catch (Exception e) {
- e.toString();
- }
- } // end run
- }
- /**
- * 中斷任務(wù)的執(zhí)行
- */
- public void pauseTaskThread() {
- setPaused();
- }
- private void setPaused() {
- synchronized (signal) {
- paused = true;
- }
- }
- private void setUnpaused() {
- synchronized (signal) {
- paused = false;
- signal.notify();
- }
- }
- /**
- * 恢復(fù)任務(wù)的執(zhí)行
- */
- public void resumeTaskThread(){
- setUnpaused();
- }
- /**
- * 終止任務(wù)的執(zhí)行
- */
- public void terminateTaskThread() {
- if (mThreadUnit != null) {
- mThreadUnit.isRunning = false;
- }
- if (mTaskQueue != null) {
- mTaskQueue.clear();
- }
- mThreadUnit = null;
- mTaskQueue = null;
- }
- }
現(xiàn)在列表中的圖片信息需要解析,如果再開一個(gè)隊(duì)列,頁面直接卡得不動了。。。
然后,這時(shí)候就考濾整個(gè)下載JS然后再下載圖片這個(gè)過程需要使用同步操作了
后來發(fā)現(xiàn),這個(gè)過程操作會比較長,頁面的開始出現(xiàn)第一項(xiàng)的圖片閃跳
原來adapter里面的getView 方法,被調(diào)用的過程中,contentview里面的內(nèi)容會被隨機(jī)復(fù)用,然后就。。。
- 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);
- }
- });
- }
- }
- });
- }
- }
值得注意的一個(gè)問題是:
settag的值需要是一個(gè)固定的值。不然,有時(shí)候會出現(xiàn)加載多次的情況。。