一、自定义消息模式的构建
例子1:自定义消息模式
Handler.java public class Handler { private Looper looper; public Handler(Looper looper){ this.looper=looper; } /**发送消息*/ public void sendMessage(Message msg){ //关联handler msg.target=this; //存储消息 looper.getMsgQ().put(msg); } /**空方法*/ public void handleMessage(Message msg){} 需要重写方法 } |
Looper.java /**借助此对象迭代消息队列*/ public class Looper { private static MessageQueue msgQ; public MessageQueue getMsgQ() { return msgQ; } private static boolean isLooper=true; /**迭代消息队列*/ public static void loop(){ while(isLooper){ //从消息队列取消息 Message msg=msgQ.take(); //交给handler处理消息 msg.target.handleMessage(msg); //target为handler对象 } } private Looper(){ msgQ=new MessageQueue(); } private static ThreadLocal<Looper> threadLocal=new ThreadLocal<>(); /**借助此方法构建Looper对象*/ public static void prepare(){ //获得当前线程绑定的looper对象 if(threadLocal.get()!=null){ throw new RuntimeException("Looper 在此线程已经存在!"); } //创建一个Looper并绑定到当前线程 threadLocal.set(new Looper()); } public static Looper myLooper(){ return threadLocal.get(); } /**退出Looper*/ public void quit(){ //从当前线程移除looper(解除绑定) threadLocal.remove(); //退出迭代 isLooper=false; } } |
Message.java public class Message { /**用于存储数据*/ Object obj; /**表是这个消息对象是要做什么*/ int what; //...... /**关联的handler对象*/ Handler target; } |
MessageQueue.java public class MessageQueue { private BlockingQueue<Message> msgQ= new ArrayBlockingQueue<>(5); /**此方法用于存储消息*/ public void put(Message msg){ try{ msgQ.put(msg); }catch(Exception e){e.printStackTrace();} } /**此方法用于取消息*/ public Message take(){ try{ return msgQ.take(); }catch(Exception e){e.printStackTrace(); return null; } } } |
例子2:主线程给工作线程发消息
public class MSWDemo01 { static Looper wLooper; public static void main( String[] args) { new Thread(){ @Override public void run() { Looper.prepare(); synchronized (MSWDemo01.class) { wLooper=Looper.myLooper(); MSWDemo01.class.notify(); } Looper.loop(); } }.start(); //主线程要给工作线程发消息必须要获得与工作线程的Looper关联的handler synchronized (MSWDemo01.class) { if(wLooper==null){ try{MSWDemo01.class.wait();}catch(Exception e){} } } Handler h=new Handler(wLooper){ public void handleMessage(Message msg) { String tname=Thread.currentThread().getName(); System.out.println(tname+"-->"+msg.obj); }; }; Message msg=new Message(); msg.obj="hello work thread"; h.sendMessage(msg); } } |
例子3:主线程给工作线程发消息
public class MSWDemo01 { static Looper wLooper; public static void main( String[] args) { new Thread(){ @Override public void run() { Looper.prepare(); synchronized (MSWDemo01.class) { wLooper=Looper.myLooper(); MSWDemo01.class.notify(); } Looper.loop(); } }.start(); //主线程要给工作线程发消息必须要获得与工作线程的Looper关联的handler synchronized (MSWDemo01.class) { if(wLooper==null){ try{MSWDemo01.class.wait();}catch(Exception e){} } } Handler h=new Handler(wLooper){ public void handleMessage(Message msg) { String tname=Thread.currentThread().getName(); System.out.println(tname+"-->"+msg.obj); }; }; Message msg=new Message(); msg.obj="hello work thread"; h.sendMessage(msg); } } |
二、handler机制
(1)/Message.obtain(handler, 1, i).sendToTarget();
(2) handler.post(new Runnable()
(3) runOnUiThread(new Runnable()
例子4:handler机制
public class MainActivity extends Activity {
private ProgressBar pBar; private ProgressDialog dialog; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
tv=(TextView) findViewById(R.id.textView1); pBar=(ProgressBar) findViewById(R.id.progressBar1); //设置进度的最大值 pBar.setMax(10);
} Handler handler; public void onClick(View v){ handler=new Handler(Looper.getMainLooper()){ public void handleMessage(Message msg) { if(msg.what==0){ pBar.setVisibility(View.VISIBLE); tv.setVisibility(View.GONE); }else if(msg.what==1){ tv.setText(msg.obj+"/10"); }else if(msg.what==2){ pBar.setVisibility(View.GONE); tv.setVisibility(View.GONE); pBar.setProgress(0); } }; }; new Thread(){ @Override public void run() { handler.sendEmptyMessage(0);//what for(int i=1;i<=10;i++){ try{sleep(500);}catch(Exception e){} //pBar.incrementProgressBy(1); pBar.setProgress(i);//严格来说也是在主线程
//Message.obtain(handler, 1, i).sendToTarget();
//Message.obtain(handler, 1, i, -1).sendToTarget();
/*handler.post(new Runnable() { @Override public void run() { //更新pBar,textView 直接更新View } });*/
/*runOnUiThread(new Runnable() { @Override public void run() { //更新pBar,textView 直接更新View
} });*/ } handler.sendEmptyMessage(2); } }.start(); } } |
例子5:分页显示数据
public class MainActivity extends ListActivity implements OnScrollListener {
private List<String> list=new ArrayList<String>(); ArrayAdapter<String> adapter; View footer; int pager=1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); footer=View.inflate(this, R.layout.progress_item_1, null); getListView().addFooterView(footer); 初始化一个布局,转化成View,再添加 loadDataFromNet(pager); adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,list); setListAdapter(adapter); getListView().setOnScrollListener(this); } /**模拟从网络加载数据*/ private void loadDataFromNet(final int page){ new Thread(){public void run(){ try{sleep(1000);}catch(Exception e){} //1.从网络获得数据str //String dataStr="";//从网络获得 //2.解析数据(xml,json) //3.将数据封装到集合 list.addAll(DataContext.getPageRecords(page)); //在主线程去更新UI runOnUiThread(new Runnable() { @Override public void run() { adapter.notifyDataSetChanged(); 刷新数据 getListView().removeFooterView(footer); } }); }}.start(); } boolean isExit; @Override public void onBackPressed() { if(!isExit){ Toast.makeText(this, "再点一次则退出", 1).show(); isExit=true; Handler h=new Handler(); //发送延迟消息 h.postDelayed(new Runnable() { @Override public void run() { isExit=false; } }, 3000);//3秒以后发送 }else{ super.onBackPressed(); } } /**滚动状态发生变化时执行此方法*/ @Override public void onScrollStateChanged( AbsListView view, //listview int scrollState) { Log.i("TAG", "scrollState="+scrollState); //假如状态为停止状态 if(scrollState==OnScrollListener.SCROLL_STATE_IDLE 滑到没数据 &&view.getLastVisiblePosition()==pager*20-1){ 滑到当前页的最后一个位置 pager++; Log.i("TAG", "page="+pager); if(pager<=DataContext.getTotalPages()){ getListView().addFooterView(footer); 添加View loadDataFromNet(pager); 加载数据 } } } /**listview滚动时就会执行此方法*/ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } } |
public class DataContext {
//假设此集合为数据库 private static List<String> dbList=new ArrayList<String>(); static{ for(int i=1;i<=100;i++){ dbList.add(String.valueOf(i)); } } /**计算总页数*/ public static int getTotalPages(){ return dbList.size()%20==0?dbList.size()/20:dbList.size()/20+1; } /**根据页码获得指定数据*/ public static List<String> getPageRecords(int page){ if(page<0)throw new IllegalArgumentException("page 不能小于0"); if(page>getTotalPages())throw new IllegalArgumentException("已经超出总页数"); //借助此集合存储每页的数据 List<String> pageList=new ArrayList<String>(); //从数据库中取数据存储到pageList for(int i=(page-1)*20;i<page*20;i++){ pageList.add(dbList.get(i)); } return pageList; } } |
progress_item_1.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >
<ProgressBar android:id="@+id/progressBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="18dp" />
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/progressBar1" android:layout_marginBottom="14dp" android:layout_toRightOf="@+id/progressBar1" android:text="正在加载数据..." />
</RelativeLayout> |