一、异步下载更新进度条
activity_down_load.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Button" android:id="@+id/button"/> <ProgressBar style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/progressBar" android:max="100" android:layout_gravity="center_horizontal"/> </LinearLayout>
DownloadActivity.java
package com.administrator.handlerproject; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.ProgressBar; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; public class DownloadActivity extends Activity { private Handler mHandler; public static final int DOWNLOAD_MESSAGE_CODE = 100001; public static final int DOWNLOAD_MESSAGE_FAIL_CODE = 100002; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_down_load); final ProgressBar progressBar = (ProgressBar)findViewById(R.id.progressBar); /** * 主线程 -->start * 点击按钮 | * 发起下载 | * 开启子线程做下载 | * 下载完成后通知主线程 | -->主线程更新进度条 */ findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { download("http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk"); } }).start(); } }); mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case DOWNLOAD_MESSAGE_CODE: progressBar.setProgress((Integer) msg.obj); case DOWNLOAD_MESSAGE_FAIL_CODE: } } }; } private void download(String appUrl){ try { URL url = new URL(appUrl); URLConnection urlConnection = url.openConnection(); InputStream inputStream = urlConnection.getInputStream(); /** * 获取文件的总长度 */ int contentLength = urlConnection.getContentLength(); String downloadFolderName = Environment.getExternalStorageDirectory() + File.separator+"imooc"+File.separator; File file = new File(downloadFolderName); if (!file.exists()){ file.mkdir(); } String fileName = downloadFolderName + "imooc.apk"; File apkFile = new File(fileName); if (apkFile.exists()){ apkFile.delete(); } int downloadSize = 0; byte[] bytes = new byte[1024]; int length = 0; OutputStream outputStream = new FileOutputStream(fileName); while ((length = inputStream.read(bytes)) != -1){ outputStream.write(bytes,0,length); downloadSize += length; /** * update UI */ Message message = Message.obtain(); message.obj = downloadSize * 100 / contentLength; message.what = DOWNLOAD_MESSAGE_CODE; mHandler .sendMessage(message); } inputStream.close(); outputStream.close(); }catch (MalformedURLException e){ notifyDownloadFaild(); e.printStackTrace(); }catch (IOException e){ notifyDownloadFaild(); e.printStackTrace(); } } private void notifyDownloadFaild(){ Message message = Message.obtain(); message.what = DOWNLOAD_MESSAGE_FAIL_CODE; mHandler .sendMessage(message); } }
二、倒计时效果(内存泄漏处理)
当Activity被销毁的时候,被延时的消息会在被处理之前存在于主线程的消息队列中,而这个消息中又包含了Handler的引用,而Handler是一个匿名内部类的实例,其持有外面的MainActivity的引用。这些引用会一直保持到该消息被处理,从而阻止了MainActivity被垃圾回收器回收。因此这就导致了MainActivity无法被回收,进而导致MainActivity持有的很多资源都无法回收,这就是我们常说的内存泄漏。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.administrator.handlerxuexi.MainActivity"> <TextView android:id="@+id/countdownTimeTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@null" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
MainActivity.java
package com.administrator.handlerxuexi; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; import java.lang.ref.WeakReference; public class MainActivity extends AppCompatActivity { /** * 倒计时标记handle code */ public static final int COUNTDOWN_TIME_CODE = 100001; /** * 倒计时间隔 */ public static final int DELAY_MILLIS = 1000; /** * 倒计时最大值 */ public static final int MAX_COUNT = 10; private TextView mCountdownTimeTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //得到控件 mCountdownTimeTextView= (TextView)findViewById(R.id.countdownTimeTextView); //创建了一个handler CountdownTimeHandler handler = new CountdownTimeHandler(this); // Handler handler = new Handler(){}强引用会出现内存泄漏, //新建了一个message Message message = Message.obtain(); message.what = COUNTDOWN_TIME_CODE; message.arg1 = MAX_COUNT; //第一次发送这个message handler.sendMessageDelayed(message,DELAY_MILLIS); } /** * 创建弱引用的CountdownTimeHandler类继承Handler * */ public static class CountdownTimeHandler extends Handler{ static final int MIN_COUNT = 0; final WeakReference<MainActivity> mWeakReference;//括号内参数是当前Activity对象 CountdownTimeHandler(MainActivity activity){//括号内参数是当前Activity对象 mWeakReference = new WeakReference<> (activity ); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); //创建一个当前的Activity接收 MainActivity activity =mWeakReference.get();//获得上面CountdownTimeHandler内定义的mWeakReference对象 switch (msg.what){ case COUNTDOWN_TIME_CODE: int value = msg.arg1; activity.mCountdownTimeTextView.setText(String.valueOf(value --)); //循环发的消息控制 if (value >= MIN_COUNT) { Message message = Message.obtain(); message.what = COUNTDOWN_TIME_CODE; message.arg1 = value; sendMessageDelayed(message, DELAY_MILLIS); } break; } } } }
三、用Handler实现打地鼠游戏
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF"> <ImageView android:id="@+id/image_view" android:layout_width="80dp" android:layout_height="80dp" android:src="@mipmap/ic_launcher" android:visibility="gone"/> <Button android:id="@+id/start_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:text="点击开始"/> <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:textAppearance="?android:attr/textAppearanceLarge"/> </RelativeLayout>
MainActivity.java
package com.administrator.diglett; import android.app.Activity; import android.content.DialogInterface; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.lang.ref.WeakReference; import java.util.Random; public class MainActivity extends AppCompatActivity implements View.OnClickListener,View.OnTouchListener{ public static final int CODE = 123; private TextView mResultTextView; private ImageView mDiglettImageView; private Button mStarrButton; public int[][] mPosition = new int[][]{ {342,180},{432,880}, {521,256},{429,780}, {456,976},{145,665}, {123,678},{564,567}, }; private int mTotalCount; private int mSuccessCount; public static final int MAX_COUNT = 10; private DialettHandler mHandler = new DialettHandler(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); setTitle("打地鼠"); } private void initView(){ mResultTextView = (TextView)findViewById(R.id.text_view); mDiglettImageView = (ImageView)findViewById(R.id.image_view); mStarrButton = (Button)findViewById(R.id.start_button); mStarrButton.setOnClickListener(this); mDiglettImageView.setOnTouchListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.start_button: start(); break; } } private void start() { //发送消息 handler.sendmessagedelayer mResultTextView.setText("开始啦"); mStarrButton.setText("游戏中....."); mStarrButton.setEnabled(false); next(0); } private void next(int delayTime){ //让地鼠每次都会有下一个 int position = new Random().nextInt(mPosition.length); Message message = Message.obtain(); message.what = CODE; message.arg1 = position; mHandler.sendMessageDelayed(message,delayTime); mTotalCount ++; } @Override public boolean onTouch(View v, MotionEvent event) { v.setVisibility(View.GONE); mSuccessCount ++; mResultTextView.setText("打到了"+mSuccessCount + "只,共" +(MAX_COUNT-1) + "只"); return false; } /** * 创建弱引用的CountdownTimeHandler类继承Handler来处理Handler的内存泄漏问题 */ public static class DialettHandler extends Handler{ public static final int RANDOM_NUBER = 500; public final WeakReference<MainActivity> mWeakReference;//括号内参数是当前Activity对象 public DialettHandler(MainActivity activity) {//括号内参数是当前Activity对象 mWeakReference = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); //创建一个当前的Activity接收 MainActivity activity = mWeakReference.get();//拿到上面的Activity switch (msg.what){ case CODE: if(activity.mTotalCount>MAX_COUNT){ activity.clear(); Toast.makeText(activity,"地鼠打完了!",Toast.LENGTH_LONG).show(); return; } int position =msg.arg1; activity.mDiglettImageView.setX(activity.mPosition[position][0]); activity.mDiglettImageView.setY(activity.mPosition[position][1]); activity.mDiglettImageView.setVisibility(View.VISIBLE); int randomTime = new Random().nextInt(RANDOM_NUBER) + RANDOM_NUBER; activity.next(randomTime); break; } } } private void clear() { mTotalCount = 0; mSuccessCount = 0; mDiglettImageView.setVisibility(View.GONE); mStarrButton.setText("点击开始"); mStarrButton.setEnabled(true); } }
。