1 import java.util.concurrent.ExecutorService;
2 import java.util.concurrent.Executors;
3 import android.app.Activity;
4 import android.app.Dialog;
5 import android.app.ProgressDialog;
6 import android.content.Context;
7 import android.os.Handler;
8 import android.os.Looper;
9 import android.os.Message;
10
11 public class UiThread {
12 private static Context mainContext;
13 private static Handler mainHandler;
14 private static ExecutorService pool;
15 // 最大执行线程数量
16 private static final int MAXTHREADCOUNT = 5;
17
18 private Object obj; // 运行时需要的obj
19 private String flag = ""; // 防止null
20 private long runDelayMillis; // 运行前延迟
21 private long callbackDelayMills; // 回调前延时
22 private Dialog dialog;
23 private UIThreadEvent event;
24 private UIpublisher publisher;
25 private Object back;
26 private Context context;
27
28 public interface UIThreadEvent {
29 public Object runInThread(String flag, Object obj, Publisher publisher);
30
31 public void runInUi(String flag, Object obj, boolean ispublish,
32 float progress);
33 }
34
35 public interface Publisher {
36 public void publishProgress(float progress);
37
38 public void publishObject(Object object);
39 }
40
41 public class PublishData {
42 Object obj;
43 float progress;
44 UiThread uithread;
45 }
46
47 public static UiThread init(Context content) {
48 return new UiThread((Activity) content);
49 }
50
51 public class UIpublisher implements Publisher {
52 public UiThread uithread;
53
54 public UIpublisher(UiThread uithread) {
55 this.uithread = uithread;
56 }
57
58 @Override
59 public void publishProgress(float progress) {
60 PublishData data = new PublishData();
61 data.uithread = uithread;
62 data.progress = progress;
63 data.obj = null;
64
65 Message msg = Message.obtain();
66 msg.obj = data;
67 mainHandler.sendMessage(msg);
68 }
69
70 @Override
71 public void publishObject(Object object) {
72 PublishData data = new PublishData();
73 data.uithread = uithread;
74 data.progress = -1;
75 data.obj = object;
76
77 Message msg = Message.obtain();
78 msg.obj = data;
79 mainHandler.sendMessage(msg);
80 }
81
82 }
83
84 public UiThread(Activity activity) {
85 this.context = activity;
86 if (mainHandler == null || mainContext != context) {
87 mainContext = context;
88
89 if (Looper.myLooper() != Looper.getMainLooper()) {
90 throw new InternalError("uiThread cannot init from thread!");
91 }
92
93 mainHandler = new Handler() {
94 @Override
95 public void handleMessage(Message msg) {
96 if (msg == null)
97 return;
98
99 Object obj = msg.obj;
100 if (obj instanceof UiThread) {
101 UiThread data = (UiThread) obj;
102 // 如果是activity,finish后就不回调mainthread
103 if (context instanceof Activity) {
104 if (((Activity) data.context).isFinishing()) {
105 return;
106 }
107 }
108
109 if (data.dialog != null) {
110 // 关闭加载窗
111 data.dialog.dismiss();
112 }
113 data.event.runInUi(data.flag, data.back, false, -1);
114
115 // 清理
116 data.dialog = null;
117 data.event = null;
118 data.publisher = null;
119 data = null;
120 } else if (obj instanceof PublishData) {
121 PublishData data = (PublishData) obj;
122
123 if (data.uithread.dialog instanceof ProgressDialog) {
124 // 如果设置显示了ProgressDialog,自动更新dialog的进度
125 if (data.uithread.dialog.isShowing()
126 && data.progress > 0 && data.progress < 100) {
127 ((ProgressDialog) data.uithread.dialog)
128 .setMessage(data.progress + "%");
129 }
130 }
131
132 data.uithread.event.runInUi(data.uithread.flag,
133 data.obj, true, data.progress);
134
135 // 清理
136 data.uithread = null;
137 data.obj = null;
138 data = null;
139 }
140 msg.obj = null;
141 }
142 };
143 }
144 if (pool == null) {
145 pool = Executors.newFixedThreadPool(MAXTHREADCOUNT); // 固定线程池
146 }
147 }
148
149 public UiThread setFlag(String flag) {
150 this.flag = flag;
151 return this;
152 }
153
154 public UiThread setObject(Object obj) {
155 this.obj = obj;
156 return this;
157 }
158
159 public UiThread showDialog(Dialog dialog) {
160 if (this.dialog != null) {
161 if (this.dialog.isShowing()) {
162 this.dialog.dismiss();
163 }
164 }
165
166 this.dialog = dialog;
167 return this;
168 }
169
170 public UiThread showDialog(String tip, boolean canCancel) {
171 if (dialog != null) {
172 if (dialog.isShowing()) {
173 dialog.dismiss();
174 }
175 }
176
177 if (tip == null) {
178 dialog = ProgressDialog.show(context, null, "加载中", true, canCancel,
179 null);
180 } else {
181 dialog = ProgressDialog.show(context, null, tip, true, canCancel,
182 null);
183 }
184 return this;
185 }
186
187 public UiThread setRunDelay(long delayMillis) {
188 this.runDelayMillis = delayMillis;
189 return this;
190 }
191
192 public UiThread setCallBackDelay(long delayMillis) {
193 this.callbackDelayMills = delayMillis;
194 return this;
195 }
196
197 public void start(UIThreadEvent event) {
198 this.event = event;
199 publisher = new UIpublisher(this);
200
201 if (dialog != null) {
202 dialog.show();
203 }
204
205 pool.execute(new Runnable() {
206 @Override
207 public void run() {
208 try {
209 Thread.sleep(runDelayMillis);
210 } catch (Exception e) {
211 e.printStackTrace();
212 }
213 UiThread.this.back = UiThread.this.event.runInThread(flag, obj,
214 publisher);
215 Message msg = Message.obtain();
216 msg.obj = UiThread.this;
217 mainHandler.sendMessageDelayed(msg, callbackDelayMills);
218 }
219 });
220 }
221 }
1 import java.io.File;
2 import java.io.FileOutputStream;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.HttpURLConnection;
6 import java.net.MalformedURLException;
7 import java.net.URL;
8
9 import org.apache.http.HttpEntity;
10 import org.apache.http.HttpResponse;
11 import org.apache.http.client.HttpClient;
12 import org.apache.http.client.methods.HttpGet;
13 import org.apache.http.impl.client.DefaultHttpClient;
14 import org.apache.http.util.EntityUtils;
15
16 import android.app.Activity;
17 import android.graphics.Bitmap;
18 import android.graphics.BitmapFactory;
19 import android.os.Bundle;
20 import android.os.Environment;
21 import android.os.Message;
22 import android.view.View;
23 import android.view.View.OnClickListener;
24 import android.widget.ImageView;
25 import android.widget.TextView;
26
27 import com.yunxun.tool.UiThread;
28 import com.yunxun.tool.UiThread.Publisher;
29 import com.yunxun.tool.UiThread.UIThreadEvent;
30
31 public class MainActivity extends Activity implements OnClickListener,
32 UIThreadEvent {
33 TextView tv;
34 ImageView img;
35
36 @Override
37 protected void onCreate(Bundle savedInstanceState) {
38 super.onCreate(savedInstanceState);
39 setContentView(R.layout.activity_main);
40 tv = (TextView) findViewById(R.id.tv);
41 img = (ImageView) findViewById(R.id.img);
42 findViewById(R.id.btn_get).setOnClickListener(this);
43 findViewById(R.id.btn_image).setOnClickListener(this);
44 findViewById(R.id.btn_nor).setOnClickListener(this);
45 findViewById(R.id.btn_down).setOnClickListener(this);
46 }
47
48 @Override
49 public void onClick(View view) {
50 switch (view.getId()) {
51 case R.id.btn_nor: // 普通操作
52 // 延迟3秒回调setCallBackDelay(3000) 执行线程延迟4秒setRunDelay(4000)
53 UiThread.init(this).setCallBackDelay(3000)
54 .showDialog("加载中...", true).setFlag("nor").start(this);
55 break;
56 case R.id.btn_get: // get操作
57 UiThread.init(this).setFlag("get").showDialog("加载中...", false)
58 .start(this);
59 break;
60 case R.id.btn_image: // 图片请求
61 UiThread.init(this).setFlag("img").start(this);
62 break;
63 case R.id.btn_down: // 下载文件
64 UiThread.init(this).setFlag("down").start(this);
65 break;
66 default:
67 break;
68 }
69 }
70
71 private static String doget() {
72 String url = "http://ptool.aliapp.com/getip";
73 HttpGet get = new HttpGet(url);
74 HttpClient client = new DefaultHttpClient();
75 try {
76 HttpResponse response = client.execute(get); // 执行get方法
77 String resultString = EntityUtils.toString(response.getEntity());
78 return resultString;
79 } catch (Exception e) {
80 }
81 return null;
82 }
83
84 private static Bitmap returnBitMap() {
85 String url = "http://ptool.aliapp.com/QRCodeEncoder?content=im-"
86 + (int) (Math.random() * 100);
87
88 URL myFileUrl = null;
89 Bitmap bitmap = null;
90 HttpURLConnection conn;
91 try {
92 myFileUrl = new URL(url);
93 } catch (MalformedURLException e) {
94 e.printStackTrace();
95 }
96
97 try {
98 conn = (HttpURLConnection) myFileUrl.openConnection();
99 conn.setDoInput(true);
100 conn.connect();
101 InputStream is = conn.getInputStream();
102 bitmap = BitmapFactory.decodeStream(is);
103 is.close();
104
105 } catch (IOException e) {
106 e.printStackTrace();
107 }
108
109 return bitmap;
110 }
111
112 public void loadFile(String url, String locPath, String filename,
113 Publisher publisher) {
114 HttpClient client = new DefaultHttpClient();
115 HttpGet get = new HttpGet(url);
116 HttpResponse response;
117 try {
118 response = client.execute(get);
119
120 HttpEntity entity = response.getEntity();
121 float length = entity.getContentLength();
122
123 InputStream is = entity.getContent();
124 FileOutputStream fileOutputStream = null;
125 if (is != null) {
126
127 String sdcard = Environment.getExternalStorageDirectory()
128 .getAbsolutePath() + "/" + locPath;
129
130 File dir = new File(sdcard);
131 if (!dir.exists()) { // 不存在则创建
132 dir.mkdirs();
133 }
134
135 File file = new File(sdcard + "/" + filename);
136 if (file.exists()) {
137 file.delete();
138 } else {
139 file.createNewFile();
140 }
141 fileOutputStream = new FileOutputStream(file);
142 byte[] buf = new byte[1024];
143 int ch = -1;
144 float count = 0;
145 while ((ch = is.read(buf)) != -1) {
146 fileOutputStream.write(buf, 0, ch);
147 count += ch;
148 float progress = count * 100f / length;
149
150 // 发布进度
151 publisher.publishProgress(progress);
152 }
153 }
154
155 // 发布成功
156 publisher.publishProgress(100f);
157
158 fileOutputStream.flush();
159 if (fileOutputStream != null) {
160 fileOutputStream.close();
161 }
162 } catch (Exception e) {
163 e.printStackTrace();
164
165 // 发布下载失败
166 publisher.publishProgress(-1);
167 }
168 }
169
170 @Override
171 public Object runInThread(String flag, Object obj,
172 UiThread.Publisher publisher) {
173 if (flag.equals("nor")) {
174 for (int i = 0; i < 10; i++) {
175 try {
176 Thread.sleep(1000);
177 } catch (Exception e) {
178 }
179 // 可以在线程中发布一个进度,runInUi时 ispublish=true,progress=发布的进度(0-100)
180 publisher.publishProgress(i * 10);
181 }
182 // 还可以发布一个object,runInUi时 ispublish=true,progress=-1
183 publisher.publishObject(new Bundle());
184
185 return new Message();
186 } else if (flag.equals("get")) {
187 return doget();
188 } else if (flag.equals("img")) {
189 return returnBitMap();
190 } else if (flag.equals("down")) {
191 // 给个publisher对象让它发布进度
192 loadFile(
193 "http://dlsw.baidu.com/sw-search-sp/soft/3a/12350/QQ6.1.1406080907.exe",
194 "Dowbload", "QQsetup.exe", publisher);
195 return "我是object!";
196 }
197 return null;
198 }
199
200 @Override
201 public void runInUi(String flag, Object obj, boolean ispublish,
202 float progress) {
203 if (flag.equals("nor")) {
204 if (ispublish) {
205 if (progress == -1) {// 发布的是object
206 tv.setText("进度:" + progress);
207 } else {// 发布的是进度
208 tv.setText("发布的obj:" + obj);
209 }
210 } else {
211 tv.setText("返回数据:" + obj);
212 }
213 } else if (flag.equals("get")) {
214 tv.setText("请求结果:" + obj);
215 } else if (flag.equals("img")) {
216 Bitmap bm = (Bitmap) obj;
217 if (bm != null) {
218 img.setImageBitmap(bm);
219 } else {
220 tv.setText("加载图片失败!");
221 }
222 } else if (flag.equals("down")) {
223 if (ispublish) {
224 tv.setText("进度:" + progress);
225 } else {
226 tv.setText("结果:" + obj);
227 }
228 }
229 }
230
231 }