好的,今天我们来接触一下进度条,和Handler。
来来来,上代码:
1. res/layout/activity_main.xml :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="点击开始按钮,启动进度条"/> <ProgressBar android:id="@+id/h_progress" android:layout_width="match_parent" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal" android:visibility="invisible" /> <ProgressBar android:id="@+id/c_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:max="100" android:progress="50" android:visibility="invisible" style="?android:attr/progressBarStyleLarge"/> <Button android:id="@+id/btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始"/> </LinearLayout>
package com.example.demo_ui4_progressbar; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.content.Context; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.ProgressBar; public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private static final int HIDE_PROGRESS = 0x1; private static final int PROGRESSING = 0x2; private Context ctx = this; private Button btnStart; private ProgressBar hProgressBar; private ProgressBar cProgressBar; private SendMessageThread sender; public int counter = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setProgressBarVisibility(true); hProgressBar = (ProgressBar) findViewById(R.id.h_progress); cProgressBar = (ProgressBar) findViewById(R.id.c_progress); btnStart = (Button) findViewById(R.id.btn_start); btnStart.setOnClickListener(startListener); } private View.OnClickListener startListener = new View.OnClickListener() { @Override public void onClick(View v) { hProgressBar.setVisibility(View.VISIBLE); cProgressBar.setVisibility(View.VISIBLE); Log.d(TAG,"sender="+sender); if( sender == null ){ sender = new SendMessageThread(); sender.start(); } } }; private class SendMessageThread extends Thread{ @Override public void run() { try { Message msg0 = new Message(); Message msg1 = new Message(); Message msg2 = new Message(); Message msg3 = new Message(); Message msg4 = new Message(); Message msg5 = new Message(); msg0.what = PROGRESSING; counter = 1 * 10; mMessageHandler.sendMessage(msg0); Thread.sleep(1 * 1000); counter = 3 * 10; msg1.what = PROGRESSING; mMessageHandler.sendMessage(msg1); Thread.sleep(1 * 2000); counter = 7 * 10; msg2.what = PROGRESSING; mMessageHandler.sendMessage(msg2); Thread.sleep(1 * 3000); counter = 8 * 10; msg3.what = PROGRESSING; mMessageHandler.sendMessage(msg3); Thread.sleep(1 * 4000); counter = 9 * 10; msg4.what = PROGRESSING; mMessageHandler.sendMessage(msg4); msg5.what = HIDE_PROGRESS; mMessageHandler.sendMessage(msg5); } catch (Exception e) { e.printStackTrace(); } finally{ sender = null; } } } private Handler mMessageHandler = new Handler(){ public void handleMessage(Message msg) { switch(msg.what){ case MainActivity.HIDE_PROGRESS: hProgressBar.setVisibility(View.GONE); cProgressBar.setVisibility(View.GONE); break; case MainActivity.PROGRESSING: hProgressBar.setProgress(counter); cProgressBar.setProgress(counter); break; default: break; } }; }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
先看看layout:
<ProgressBar android:id="@+id/h_progress" android:layout_width="match_parent" android:layout_height="wrap_content" style="?android:attr/progressBarStyleHorizontal" android:visibility="invisible" /> <ProgressBar android:id="@+id/c_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:max="100" android:progress="50" android:visibility="invisible" style="?android:attr/progressBarStyleLarge"/>这里是两个进度条,上面一个是水平进度条,下面一个是圆形转的进度条,两个进度条是通过?android:arrt/... 来设置的,当然还有其他样式的进度条,自己可以去查一下。我们主要来看看怎么使用进度条。我们用进度条主要是因为一些耗时的操作,如果界面一直卡着不动,那么用户体验就相当不好,所以我们需要一个表示进度的控件来提示用户现在进行到哪一步了,所以有了进度条这么一个东西。
这里我们为了模仿一个过程,所以启动了一个线程,每次点击开始按钮,我们判断:如果线程在运行(不为null)那么就不响应,如果过程没有开始,那么我们就启动一个线程来模拟一个过程。来看看线程中实现了什么:
<pre name="code" class="java"> try { Message msg0 = new Message(); Message msg1 = new Message(); Message msg2 = new Message(); Message msg3 = new Message(); Message msg4 = new Message(); Message msg5 = new Message(); msg0.what = PROGRESSING; counter = 1 * 10; mMessageHandler.sendMessage(msg0); Thread.sleep(1 * 1000); counter = 3 * 10; msg1.what = PROGRESSING; mMessageHandler.sendMessage(msg1); Thread.sleep(1 * 2000); counter = 7 * 10; msg2.what = PROGRESSING; mMessageHandler.sendMessage(msg2); Thread.sleep(1 * 3000); counter = 8 * 10; msg3.what = PROGRESSING; mMessageHandler.sendMessage(msg3); Thread.sleep(1 * 4000); counter = 9 * 10; msg4.what = PROGRESSING; mMessageHandler.sendMessage(msg4); msg5.what = HIDE_PROGRESS; mMessageHandler.sendMessage(msg5); } catch (Exception e) { e.printStackTrace(); } finally{ sender = null; }这里定义了6个Message对象,每一个对象表示这个过程进行到了哪一步,那么这时候进度条就应该显示到某个位置。最后要发送一个消息说:过程完了,把进度条隐藏吧!(HIDE_PROGRESS), 如果还在过程中,我们就会发送(PROGRESSING)的消息,这样Handler收到之后就会更新进度条。 Message 的 what属性就是用来表示这个Message是用来干什么的。当然Message还可以携带数据,使用Message的 obj 对象,可以传递想要的数据,android框架设计这个东西早就知道我们要使用,所以不得不瞻仰一下啊。
然后发送消息过后呢?我们来看看是在什么地方处理这些消息:
private Handler mMessageHandler = new Handler(){ public void handleMessage(Message msg) { switch(msg.what){ case MainActivity.HIDE_PROGRESS: hProgressBar.setVisibility(View.GONE); cProgressBar.setVisibility(View.GONE); break; case MainActivity.PROGRESSING: hProgressBar.setProgress(counter); cProgressBar.setProgress(counter); break; default: break; } }; };终于出来了,是一个叫 Handler的对象,看他的名字就知道是一个管理者,专门来管理Message消息。 用 mMessageHandler每调用一次 sendMessage(msg), 这边的Handler就会收到一个消息,处理就在 handleMessage() 当中,判断 msg.what 这个消息是用来干什么的,如果是 HIDE_PROGRESS,那么我们就隐藏它, 如果是PROGRESSING, 我们就调用ProgressBar 的 setProgress(counter)方法来设置进度,多开心啊!
至于为什么要使用Handler呢? 如果你直接在一个线程(非UI主线程)调用UI组件的改变UI的方法,那么程序会直接崩掉,因为android中不允许非UI主线程来修改UI,所以提供了Handler这么一个玩意儿,如果你一个线程什么的想改变UI,那么好,你给我发消息,我来帮你改。这样也可以做到集中管理,就是说,我一个Activity里面可能起很多歌线程,这些线程都想修改UI,那么你只需要发消息给我就行了,我来帮你搞定。 当然这样理解比较肤浅,Handler肯定不止这个作用,其他的用处以后再来探索!
好了,今天写到这里。