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 }