使用AsyncTask实现文件下载并且在状态中显示下载进度

2013年10月24日  上班的第二天

  昨天我是用afinal完成的则个功能,但是公司里并不希望使用第三方的代码,所以要求我在不使用第三方开源项目的情况下实现。

 

  最先我是使用Thread开启一个子线程,在这个线程中完成文件下载,然后使用Handler异步消息来更新Notification中的进度条,废了九牛二虎之力,虽然完成了功能,但是做出的效果就是特别的卡,甚至连通知栏下拉都被冻结了。

  后来我尝试了AsyncTask,很轻松的完成了下载和进度值的计算,但是在通知栏中改变进度条的进度,依然会出现卡屏的问题。

  最后在StackOverFlow中查找解决方案,给出的答案是,在更新Notification的时候,使用Handler来更新进度条进度,更新的频率特别高,再次期间会不断的生成RemoteViews对象,所以消耗了大量的内存。虽然没有看到实实在在的代码,但是有了解决的思路。

  1.降低Handler的更新的频率;

  2.尽量能够复用RemoteViews的对象。

  

  对应的具体的实现是用计数器来控制更新的频率,用静态的RemoteViews对象。

  

  后面上代码:

  主界面的布局文件:activity_main.xml

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:padding="10dp"
 6     tools:context=".MainActivity" >
 7 
 8     <TextView
 9         android:id="@+id/hint_tv"
10         android:layout_width="wrap_content"
11         android:layout_height="wrap_content"
12         android:paddingTop="10dp"
13         android:text="@string/tv_main_hint" />
14 
15     <EditText
16         android:id="@+id/url_et"
17         android:layout_width="match_parent"
18         android:layout_height="wrap_content"
19         android:layout_toRightOf="@id/hint_tv"
20         android:hint="@string/et_downloadurl"
21         android:singleLine="true" />
22 
23     <Button
24         android:id="@+id/downloadBtn"
25         android:layout_width="match_parent"
26         android:layout_height="wrap_content"
27         android:layout_below="@id/url_et"
28         android:paddingTop="20dp"
29         android:text="@string/str_download" />
30     
31      <Button
32          android:layout_below="@id/downloadBtn"
33         android:id="@+id/pauseBtn"
34         android:layout_width="match_parent"
35         android:layout_height="wrap_content"
36         android:paddingTop="20dp"
37         android:text="@string/btn_pause" />
38      
39      <Button
40          android:layout_below="@id/pauseBtn"
41         android:id="@+id/continueBtn"
42         android:layout_width="match_parent"
43         android:layout_height="wrap_content"
44         android:paddingTop="20dp"
45         android:text="@string/btn_continue" />
46      
47     
48      <ProgressBar
49          android:layout_below="@id/continueBtn"
50         android:id="@+id/pb"
51         style="?android:attr/progressBarStyleHorizontal"
52         android:layout_width="match_parent"
53         android:layout_height="wrap_content"
54         android:paddingTop="20dp" />
55      
56      <TextView
57          android:layout_below="@id/pb"
58         android:id="@+id/progressTV"
59         android:text="0%"
60         android:layout_centerHorizontal="true"
61         android:layout_width="wrap_content"
62         android:layout_height="wrap_content"
63         android:paddingTop="20dp" />
64      
65 
66 RelativeLayout>

自定义Notification的布局文件: notify_vew.xml

 1 xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="fill_parent"
 4     android:layout_height="fill_parent" >
 5 
 6     <ImageView
 7         android:id="@+id/notify_icon"
 8         android:layout_width="wrap_content"
 9         android:layout_height="wrap_content"
10         android:src="@drawable/ic_launcher" />
11 
12     <TextView
13         android:id="@+id/tv"
14         android:layout_width="wrap_content"
15         android:layout_height="wrap_content"
16         android:layout_toRightOf="@id/notify_icon"
17         android:singleLine="true"
18         android:text="下载进度..." />
19 
20     <ProgressBar
21         android:id="@+id/pb"
22         style="?android:attr/progressBarStyleHorizontal"
23         android:layout_width="match_parent"
24         android:layout_height="wrap_content"
25         android:layout_below="@id/tv"
26         android:layout_toRightOf="@id/notify_icon"
27         android:max="100"
28         android:paddingRight="10dp"
29         android:progress="50"
30         android:secondaryProgress="74"
31         android:visibility="visible" />
32 
33 RelativeLayout>

 

strings.xml

 1 xml version="1.0" encoding="utf-8"?>
 2 <resources>
 3 
 4     <string name="app_name">DownLoaderstring>
 5     <string name="action_settings">Settingsstring>
 6     <string name="hello_world">Hello world!string>
 7     <string name="tv_main_hint">下载地址:string>
 8     <string name="et_downloadurl">请输入下载地址string>
 9     <string name="str_download">开始下载string>
10     <string name="btn_pause">暂停下载string>
11     <string name="btn_continue">继续下载string>
12 
13 resources>

在清单文件中申请的权限:AndroidManifest.xml

1 <uses-permission android:name="android.permission.INTERNET"/>
2     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

 

MainActivity.java

  1 package com.yt.asynctaskdemo;
  2 
  3 import java.io.FileOutputStream;
  4 
  5 import java.io.IOException;
  6 import java.io.InputStream;
  7 import java.io.OutputStream;
  8 import java.net.MalformedURLException;
  9 import java.net.URL;
 10 import java.net.URLConnection;
 11 
 12 
 13 
 14 
 15 import android.os.AsyncTask;
 16 import android.os.Bundle;
 17 import android.os.Environment;
 18 import android.os.Handler;
 19 import android.os.Message;
 20 import android.app.Activity;
 21 import android.app.Notification;
 22 import android.app.NotificationManager;
 23 import android.app.PendingIntent;
 24 import android.content.Context;
 25 import android.content.Intent;
 26 import android.util.Log;
 27 import android.view.View;
 28 import android.view.View.OnClickListener;
 29 import android.widget.Button;
 30 import android.widget.EditText;
 31 import android.widget.ProgressBar;
 32 import android.widget.RemoteViews;
 33 import android.widget.TextView;
 34 
 35 public class MainActivity extends Activity {
 36 
 37     public static final String TAG = "MainActivity";
 38     
 39     private int count;
 40     private int current;
 41     private EditText downloadUrlEt;
 42     private Button downloadBtn;
 43     private Button pauseBtn;
 44     private Button continueBtn;
 45     private ProgressBar pb;
 46     private int progress;
 47     private TextView progressTV;
 48     private boolean finished;
 49     private boolean paused;
 50     private NotificationManager manager;
 51     private Notification notification;
 52     private static RemoteViews contentView;
 53     
 54     
 55     private int times;
 56 
 57     private MyAsyncTask mTask;
 58 
 59     private Handler handler = new Handler(){
 60         public void handleMessage(android.os.Message msg) {
 61             if(contentView == null){
 62                 contentView = new RemoteViews(getPackageName(), R.layout.notify_view);
 63                 contentView.setProgressBar(R.id.pb, 100, 0, false);
 64                 notification.icon = R.drawable.ic_launcher;
 65                 notification.tickerText = "下载进度";
 66                 notification.flags = notification.DEFAULT_ALL;
 67                 notification.contentView = contentView;
 68                 PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this, 0,
 69                         new Intent(MainActivity.this, MainActivity.class), 0);
 70 
 71                 notification.setLatestEventInfo(MainActivity.this, "你好!",
 72                                "byebye", contentIntent);
 73                 manager.notify(0, notification);
 74             }
 75             if(times++ % 5 == 0 || progress==100){
 76                 contentView.setProgressBar(R.id.pb, 100, progress, false);
 77                 notification.contentView = contentView;
 78                 manager.notify(0, notification);
 79             }
 80             super.handleMessage(msg);
 81         };
 82     };
 83     @Override
 84     protected void onCreate(Bundle savedInstanceState) {
 85         super.onCreate(savedInstanceState);
 86         setContentView(R.layout.activity_main);
 87         downloadUrlEt = (EditText) findViewById(R.id.url_et);
 88         downloadUrlEt.setText("http://mit.95195.com/singleonline.apk");
 89         downloadBtn = (Button) findViewById(R.id.downloadBtn);
 90         pauseBtn = (Button) findViewById(R.id.pauseBtn);
 91         continueBtn = (Button) findViewById(R.id.continueBtn);
 92         progressTV = (TextView) findViewById(R.id.progressTV);
 93         pb = (ProgressBar) findViewById(R.id.pb);
 94         MyOnClickListener listener = new MyOnClickListener();
 95         downloadBtn.setOnClickListener(listener);
 96         pauseBtn.setOnClickListener(listener);
 97         continueBtn.setOnClickListener(listener);
 98         mTask = new MyAsyncTask();    
 99         manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
100         notification = new Notification(R.drawable.ic_launcher, "下载进度条...",System.currentTimeMillis());
101     }
102 
103 
104     /**
105      * 按钮事件监听
106      * 
107      * @author yt
108      * 
109      */
110     class MyOnClickListener implements OnClickListener {
111 
112         @Override
113         public void onClick(View v) {
114             switch (v.getId()) {
115             case R.id.downloadBtn:
116                 mTask.execute("http://mit.95195.com/singleonline.apk");
117                 break;
118 
119             case R.id.pauseBtn:
120                 paused = true;
121                 break;
122 
123             case R.id.continueBtn:            
124                 paused = false;
125                 break;
126             }
127         }
128 
129     }
130     
131     
132     class MyAsyncTask extends AsyncTask{
133         @Override
134         protected String doInBackground(String... params) {
135             try {
136                 URL url = new URL(params[0]);
137                 URLConnection conn = url.openConnection();
138                 count = conn.getContentLength();
139                 InputStream is = conn.getInputStream();
140                 OutputStream os = new FileOutputStream(Environment.getExternalStorageDirectory()+"/singleon.apk");
141                 byte[] buffer = new byte[1024];
142                 int len = -1;
143                 while(!finished){
144                     while(!paused && (len = is.read(buffer))>0){
145                             current += len;
146                             os.write(buffer,0,len);
147                             progress = current * 100 / count;
148 //                            Log.i(TAG, "current = " + current + " count = " + count + " progress = " + progress);
149                             publishProgress(progress);    
150                             Message msg = new Message();
151                             handler.handleMessage(msg);
152                     }        
153                 }
154                 
155             } catch (MalformedURLException e) {
156                 e.printStackTrace();
157             } catch (IOException e) {;
158                 e.printStackTrace();
159             }
160             
161             return progress+"";
162         }    
163         
164         @Override
165         protected void onPostExecute(String result) {
166             Log.i(TAG, result+"");
167             super.onPostExecute(result);
168         }
169         
170         
171         @Override
172         protected void onProgressUpdate(Integer... values) {
173             
174             if(values[0]==99){
175                 finished = true;
176                 manager.cancel(0);
177             }        
178             progressTV.setText(values[0]+"");
179             pb.setProgress(progress);
180             super.onProgressUpdate(values);        
181         }
182         
183         @Override
184         protected void onPreExecute() {
185             handler.handleMessage(new Message());
186             super.onPreExecute();
187         }
188         
189     }
190     
191 }

完整代码下载:http://download.csdn.net/detail/yuan936845015/6450041

转载于:https://www.cnblogs.com/hungryt/p/asynctask_1.html

你可能感兴趣的:(使用AsyncTask实现文件下载并且在状态中显示下载进度)