Android系统以不同寻常的方式处理多个应用程序的同时运行。来自于其它不同平台的开发者或许会对这样的运行机制感到很奇怪。而理解Android多任务的运行,对于设计出可以良好运行的应用程序,以及与Android平台的其它部分进行无缝结合都具有重要意义。这篇文章说明了Android的多任务方式设计上的成因,它对应用程序运行产生的影响,还有你可以怎样更好地利用Android的这一特性。
近期项目中,遇到一个问题,列表数据中的图片地址是一个需要下载JS再解析的字段,之前的图片下载是一个异步的过程,由一个队列处理。
复制
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() { synchronized (signal) { 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; } }
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
现在列表中的图片信息需要解析,如果再开一个队列,页面直接卡得不动了。。。
然后,这时候就考滤整个下载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); } }); } } }); } }
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
值得注意的一个问题是:
settag的值需要是一个固定的值。不然,有时候会出现加载多次的情况。。