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

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

 

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

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

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

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

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

  

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

  

  后面上代码:

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

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
tools:context=".MainActivity" > <TextView
android:id="@+id/hint_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:text="@string/tv_main_hint" /> <EditText
android:id="@+id/url_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/hint_tv"
android:hint="@string/et_downloadurl"
android:singleLine="true" /> <Button
android:id="@+id/downloadBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/url_et"
android:paddingTop="20dp"
android:text="@string/str_download" /> <Button
android:layout_below="@id/downloadBtn"
android:id="@+id/pauseBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:text="@string/btn_pause" /> <Button
android:layout_below="@id/pauseBtn"
android:id="@+id/continueBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:text="@string/btn_continue" /> <ProgressBar
android:layout_below="@id/continueBtn"
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp" /> <TextView
android:layout_below="@id/pb"
android:id="@+id/progressTV"
android:text="0%"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="20dp" /> </RelativeLayout>

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

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <ImageView
android:id="@+id/notify_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" /> <TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/notify_icon"
android:singleLine="true"
android:text="下载进度..." /> <ProgressBar
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv"
android:layout_toRightOf="@id/notify_icon"
android:max="100"
android:paddingRight="10dp"
android:progress="50"
android:secondaryProgress="74"
android:visibility="visible" /> </RelativeLayout>

strings.xml

 <?xml version="1.0" encoding="utf-8"?>
<resources> <string name="app_name">DownLoader</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="tv_main_hint">下载地址:</string>
<string name="et_downloadurl">请输入下载地址</string>
<string name="str_download">开始下载</string>
<string name="btn_pause">暂停下载</string>
<string name="btn_continue">继续下载</string> </resources>

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

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

MainActivity.java

 package com.yt.asynctaskdemo;

 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; import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
import android.widget.TextView; public class MainActivity extends Activity { public static final String TAG = "MainActivity"; private int count;
private int current;
private EditText downloadUrlEt;
private Button downloadBtn;
private Button pauseBtn;
private Button continueBtn;
private ProgressBar pb;
private int progress;
private TextView progressTV;
private boolean finished;
private boolean paused;
private NotificationManager manager;
private Notification notification;
private static RemoteViews contentView; private int times; private MyAsyncTask mTask; private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
if(contentView == null){
contentView = new RemoteViews(getPackageName(), R.layout.notify_view);
contentView.setProgressBar(R.id.pb, 100, 0, false);
notification.icon = R.drawable.ic_launcher;
notification.tickerText = "下载进度";
notification.flags = notification.DEFAULT_ALL;
notification.contentView = contentView;
PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this, 0,
new Intent(MainActivity.this, MainActivity.class), 0); notification.setLatestEventInfo(MainActivity.this, "你好!",
"byebye", contentIntent);
manager.notify(0, notification);
}
if(times++ % 5 == 0 || progress==100){
contentView.setProgressBar(R.id.pb, 100, progress, false);
notification.contentView = contentView;
manager.notify(0, notification);
}
super.handleMessage(msg);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadUrlEt = (EditText) findViewById(R.id.url_et);
downloadUrlEt.setText("http://mit.95195.com/singleonline.apk");
downloadBtn = (Button) findViewById(R.id.downloadBtn);
pauseBtn = (Button) findViewById(R.id.pauseBtn);
continueBtn = (Button) findViewById(R.id.continueBtn);
progressTV = (TextView) findViewById(R.id.progressTV);
pb = (ProgressBar) findViewById(R.id.pb);
MyOnClickListener listener = new MyOnClickListener();
downloadBtn.setOnClickListener(listener);
pauseBtn.setOnClickListener(listener);
continueBtn.setOnClickListener(listener);
mTask = new MyAsyncTask();
manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notification = new Notification(R.drawable.ic_launcher, "下载进度条...",System.currentTimeMillis());
} /**
* 按钮事件监听
*
* @author yt
*
*/
class MyOnClickListener implements OnClickListener { @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.downloadBtn:
mTask.execute("http://mit.95195.com/singleonline.apk");
break; case R.id.pauseBtn:
paused = true;
break; case R.id.continueBtn:
paused = false;
break;
}
} } class MyAsyncTask extends AsyncTask<String, Integer, String>{
@Override
protected String doInBackground(String... params) {
try {
URL url = new URL(params[0]);
URLConnection conn = url.openConnection();
count = conn.getContentLength();
InputStream is = conn.getInputStream();
OutputStream os = new FileOutputStream(Environment.getExternalStorageDirectory()+"/singleon.apk");
byte[] buffer = new byte[1024];
int len = -1;
while(!finished){
while(!paused && (len = is.read(buffer))>0){
current += len;
os.write(buffer,0,len);
progress = current * 100 / count;
// Log.i(TAG, "current = " + current + " count = " + count + " progress = " + progress);
publishProgress(progress);
Message msg = new Message();
handler.handleMessage(msg);
}
} } catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {;
e.printStackTrace();
} return progress+"";
} @Override
protected void onPostExecute(String result) {
Log.i(TAG, result+"");
super.onPostExecute(result);
} @Override
protected void onProgressUpdate(Integer... values) { if(values[0]==99){
finished = true;
manager.cancel(0);
}
progressTV.setText(values[0]+"");
pb.setProgress(progress);
super.onProgressUpdate(values);
} @Override
protected void onPreExecute() {
handler.handleMessage(new Message());
super.onPreExecute();
} } }

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

使用AsyncTask实现文件下载并且在状态中显示下载进度的更多相关文章

  1. Android开发之文件下载,状态时显示下载进度,点击自动安装

    在进行软件升级时,需要进行文件下载,在这里实现自定义的文件下载,并在状态栏显示下载进度,下载完成后,点击触发安装. 效果如图: 用于下载文件和显示现在进度的线程类如下: [java]  view pl ...

  2. Android中如何下载文件并显示下载进度

    原文地址:http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1125/2057.html 这里主要讨论三种方式:AsyncTask.Serv ...

  3. 使用afinal下载文件并且在状态栏中显示下载的进度

    2013年10月23日,今天是在“我在找你信息服务有限公司”第一天上班,公司给提出了这样一个要求:下载本公司的app,并且在下载的过程中要在状态栏中显示下载的进度,并且,可以暂停和继续下载. 下面是我 ...

  4. [iOS 多线程 & 网络 - 2.4] - 大文件下载 (边下边写/暂停恢复下载/压缩解压zip/多线程下载)

    A.需求 边下边写入硬盘 显示下载进度 暂停/恢复 下载 解压文件 多线程下载   B.基本知识 1.小文件下载 如果文件比较小,下载方式会比较多直接用NSData的+ (id)dataWithCon ...

  5. 在Installshield的安装进度中显示自己设置的信息

    原文:在Installshield的安装进度中显示自己设置的信息 以Installscript msi project为例,在installshield所制作的安装包安装过程中显示安装进度的,就在On ...

  6. (数据科学学习手札91)在Python中妥善使用进度条

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在日常运行程序的过程中常常涉及到循环迭代过程,对 ...

  7. Android中使用AsyncTask实现文件下载以及进度更新提示

    Android提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单.相对Handler来说AsyncTask更轻量级一些,适用于简单的异步处理,不需要借助线程和 ...

  8. ssis package 在调试状态中设置断点,程序 不进入断点 的解决方案

    原文:ssis package 在调试状态中设置断点,程序 不进入断点 的解决方案 针对 SSIS intergation 项目 > 属性 > Debug >Run64bITRunt ...

  9. 接上一篇中记录Echarts进度环使用【不同状态不同进度环颜色及圈内文字】--采用单实例业务进行说明

    接上一篇中记录Echarts进度环使用 此处处理不同状态下不同进度环颜色及圈内文字等的相关处理,采用实际案例源码说明 -----------------偶是华丽丽分割线---------------- ...

随机推荐

  1. Ubuntu 12.04搭建l2tp服务器记录。

    1. 安装openswan apt-get install openswan 2.打开 /etc/ipsec.conf 文件,做如下配置: 其中,virtual_privat这里包含的网络地址允许配置 ...

  2. Redis的持久化的两种方式drbd以及aof日志方式

    redis的持久化配置: 主要包括两种方式:1.快照  2 日志 来看一下redis的rdb的配置选项和它的工作原理: save 900 1 // 表示的是900s内,有1条写入,则产生快照 save ...

  3. DAO模式应用实例

    首先在数据库中建好一个表. 然后创建一个MsterDao类的接口 package com.beiwo.epte.dao; import com.beiwo.epte.entity.Master; pu ...

  4. HTTP权威协议笔记-4.连接管理

    4.1 TCP连接 TCP为HTTP提供了一条可靠的比特传输管道,按顺序正确的传输,步骤如下: 浏览器解析主机名. 查询这个主机名的IP地址(DNS) 获得端口号. 浏览器对服务器该端口号发起连接. ...

  5. MSSQL日志传送出现“LSN 太晚,无法应用到数据库”

    一个月之前配置了日志传送的数据库,在今天早上收到作业警报:"LSRestore_ServerName_Databasename"运行失败,到历史记录中查看,错误信息如下 消息 20 ...

  6. 关于 Dev中的GridControl 中 GridView 的 PopulateColumns() 方法

    最近使用Dev控件,Gridview绑定数据源后不能显示数据,于是在网上查询,说是使用PopulateColumns()方法,可以显示数据.试了一下,管用. 于是在所有更新数据源数据后,都用上了这句话 ...

  7. WCF之Binding详解

    本文的出发点: 通过阅读本文,您能了解以下知识: WCF中的Binding是什么? Binding的组 成? Binding Element 的分类? Binding描述 了那些层面的信息? 选择正确 ...

  8. Java编写最大公约数和最小公倍数

    package javaapplication24; class NegativeIntegerException extends Exception{ String message; public ...

  9. Net分布式系统之三:Keepalived+LVS+Nginx负载均衡之高可用

    上一篇写了nginx负载均衡,此篇实现高可用(HA).系统整体设计是采用Nginx做负载均衡,若出现Nginx单机故障,则导致整个系统无法正常运行.针对系统架构设计的高可用要求,我们需要解决Nginx ...

  10. Head First Html and CSS学习笔记之HTML

    初学前端开发,记录下自己的学习笔记. 第一章 认识HTML 1:关于HTML HTML是超文本标记语言(HyperText Markup Language)的缩写,用来建立网页的结构. 它只会根据标记 ...