自己写的下载
主要用到观察者模式,多个页面同步ui进度,页面流畅不错乱
下面是被观察者
package com.anjoyo.gamecenter5.loader;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.Observable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.util.Log;
import com.anjoyo.gamecenter5.GameCenter5Application;
import com.anjoyo.gamecenter5.apktools.Cons;
import com.anjoyo.gamecenter5.apktools.DownloadFile;
import com.anjoyo.gamecenter5.apktools.MyDb;
import com.anjoyo.gamecenter5.constant.WifiDialog;
import com.anjoyo.gamecenter5.fragment.TabDFm_Management;
import com.anjoyo.gamecenter5.interf.DownloadListener;
import com.anjoyo.gamecenter5.tools.ConnectionUtil;
import com.anjoyo.gamecenter5.tools.SharedpreferensUitls;
import com.anjoyo.gamecenter5.tools.ToastUtil;
//继承Observealbe成为给观察者
public class Observed extends Observable implements DownloadListener {
private Downloader downloader;
// ===========================
private static final int BUFFER_SIZE = 1024;
private URL url;
private File file;
private int startPostion;
private int endPostion;
private int curPosition;
private boolean finished = false;
private int downloadSize = 0;
private MyDb myDb;
private DownloadFile downloadFile;
private GameCenter5Application myApp;
private int opention;
private Context context;
private int fileSize;
private static ExecutorService es = Executors.newFixedThreadPool(3);
//构造方法只在DownloadManager里使用使同一个下载公用一个被观察者
public Observed(DownloadListener downloadListener,
final DownloadFile downloadFile1, Context context) {
this.context = context;
myApp = ((GameCenter5Application) context.getApplicationContext());
myDb = MyDb.getInstance(context);
Map<String, DownloadFile> hashMap = myApp.getFileMap();
if (hashMap.containsKey(downloadFile1.appPackageName)) {
this.downloadFile = myApp.getFileMap().get(
downloadFile1.appPackageName);
} else {
this.downloadFile = downloadFile1;
final String addr = downloadFile.downLoadAddress;
new Thread() {
@Override
public void run() {
try {
URL url = new URL(addr);
downloadFile.fileSize = url.openConnection()
.getContentLength();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.run();
}
}.start();
}
if (TabDFm_Management.appIsStalled(downloadFile.appPackageName,
downloadFile.version))
downloadFile.downloadState = Cons.INSTALLED;
}
public Downloader getDownloader() {
return downloader;
}
//在更新ui布局是调用,得到下载的当前状态
public DownloadFile replaceBean() {
return downloadFile;
}
public class Downloader implements Runnable {
private DownloadListener downloadListener;
private DownloadFile downloadFile;
public Downloader(DownloadListener downloadListener,
DownloadFile downloadFile) {
this.downloadListener = downloadListener;
this.downloadFile = downloadFile;
try {
url = new URL(downloadFile.downLoadAddress);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
BufferedInputStream bis = null;
RandomAccessFile fos = null;
byte[] buf = new byte[BUFFER_SIZE];
URLConnection con = null;
curPosition = startPostion = downloadFile.downloadSize;
endPostion = downloadFile.fileSize;
String downloadDir = Environment.getExternalStorageDirectory()
+ "/anjoyodownload/";
File file = new File(downloadDir);
if (!file.exists()) {
file.mkdirs();
}
myDb.updateGameDownload(downloadFile);
myApp.getApplicationContext()
.sendBroadcast(new Intent("ddownload"));
int fileNameStart = downloadFile.downLoadAddress.lastIndexOf("/");
String fileName = downloadFile.downLoadAddress
.substring(fileNameStart);
file = new File(file, fileName);
try {
Log.d("FileDownloadThread", "========" + url);
con = url.openConnection();
con.setAllowUserInteraction(true);
con.setRequestProperty("Range", "bytes=" + startPostion + "-"
+ endPostion);
fos = new RandomAccessFile(file, "rw");
fos.seek(startPostion);
bis = new BufferedInputStream(con.getInputStream());
int updateSize = 0;
if (SharedpreferensUitls.getTagWifi(context) == 1
&& ConnectionUtil.getConnectedType(context) != 1) {
// 非Wifi提示对话框
Log.d("vivi",
"wifi状态====="
+ SharedpreferensUitls.getTagWifi(context));
Log.d("vivi",
"网络状态====="
+ ConnectionUtil.getConnectedType(context));
WifiDialog.showWifiDialog(context);
} else {
myApp.addThread();
downloadFile.downloadState = Cons.LOADING;
while (curPosition < endPostion
& Cons.LOADING == downloadFile.downloadState) {
if (!ConnectionUtil.isConn(myApp))
downloadFile.downloadState = Cons.FAIL;
int len = bis.read(buf, 0, BUFFER_SIZE);
if (len == -1) {
break;
}
fos.write(buf, 0, len);
curPosition = curPosition + len;
updateSize += len;
if (curPosition > endPostion) {
downloadFile.downloadSize += len
- (curPosition - endPostion) + 1;
} else {
downloadFile.downloadSize += len;
}
if (updateSize >= downloadFile.fileSize / 100) {
//达到一定的状态,通知观察者更新
Observed.this.setChanged();
Observed.this.notifyObservers();
updateSize = 0;
}
// downloadFile.downloadSize += downloadSize;
myDb.updateGameDownload(downloadFile);
// this.finished = true;
}
}
if (curPosition >= endPostion)
downloadFile.downloadState = Cons.COMPLETE;
} catch (IOException e) {
// TODO Auto-generated catch block
downloadFile.downloadState = Cons.FAIL;
e.printStackTrace();
} finally {
//完成,通知观察者更新
Observed.this.setChanged();
Observed.this.notifyObservers();
myApp.cutThread();
if (downloadFile != null)
myDb.updateGameDownload(downloadFile);
myApp.getApplicationContext().sendBroadcast(
new Intent("ddownload"));
try {
if (bis != null)
bis.close();
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Override
public void start() {
// TODO Auto-generated method stub
if (myApp.threadNum < 3) {
this.downloadFile.downloadState = Cons.LOADING;
opention = Cons.LOADING;
} else {
this.downloadFile.downloadState = Cons.WAITING;
opention = Cons.WAITING;
}
downloader = new Downloader(null, downloadFile);
// downloader.setName(downloadFile.appPackageName);
downloadFile.threadName = downloadFile.appPackageName;
//开始一个下载,通知所有观察者更新
Observed.this.setChanged();
Observed.this.notifyObservers();
if (downloadFile != null)
myDb.updateGameDownload(downloadFile);
myApp.getApplicationContext().sendBroadcast(new Intent("ddownload"));
es.execute(downloader);
}
@Override
public void pause() {
// TODO Auto-generated method stub
this.opention = Cons.SUSPEND;
downloadFile.downloadState = Cons.SUSPEND;
Observed.this.setChanged();
Observed.this.notifyObservers();
}
@Override
public void cancle() {
// TODO Auto-generated method stub
this.opention = Cons.CANCLE;
MyDb.getInstance(context).deleteGameDownload(downloadFile.downLoadAddress);
Observed.this.setChanged();
Observed.this.notifyObservers();
}
@Override
public void waiting() {
}
}
下边是下载管理
package com.anjoyo.gamecenter5.loader;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.util.Log;
import com.anjoyo.gamecenter5.apktools.DownloadFile;
import com.anjoyo.gamecenter5.interf.DownloadListener;
/**
* 单例DownloadManager
*
* @author czt
*
*/
public class DownloadManager {
private static DownloadManager loadManager;
private Map<String, Observed> loadMap;
private DownloadManager() {
this.loadMap = new HashMap<String, Observed>();
}
public void putObserved(String key, Observed observed) {
this.loadMap.put(key, observed);
}
public Observed getObserved(DownloadListener downloadListener,
DownloadFile downloadFile, Context context) {
Observed observed = null;
if (this.loadMap.containsKey(downloadFile.appPackageName)) {
observed = this.loadMap.get(downloadFile.appPackageName);
downloadFile = observed.replaceBean();
} else {
observed = new Observed(downloadListener, downloadFile, context);
putObserved(downloadFile.appPackageName, observed);
}
Log.d("downloadmaneger", "downloadMap==--->>>>>>>>" + this.loadMap);
return observed;
}
/**
* 得到Manager的实例
*
* @return
*/
public static DownloadManager getManager() {
if (loadManager == null) {
loadManager = new DownloadManager();
}
return loadManager;
}
}
下边是观察者布局里的要更新的view封装在一个继承此观察者的类里
package com.anjoyo.gamecenter5.loader;
import java.util.Observer;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* adapter里填充的view工具
*
* @author czt
*
*/
public class ViewHolder implements Observer {
private UpdateListener listener;
public ViewHolder() {
}
public void setUpdateListener(UpdateListener listener) {
this.listener = listener;
}
@Override
public void update(java.util.Observable observable, Object data) {
if (this.listener != null) {
listener.update();
}
}
public interface UpdateListener {
void update();
}
}
Adapter里的要填充的布局(所有Adapter)
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = mInflater
.inflate(R.layout.rankinglistview_item, null);
viewHolder.txtView_Title = (TextView) convertView
.findViewById(R.id.ranking_item_title);
viewHolder.txtView_FileSize = (TextView) convertView
.findViewById(R.id.ranking_item_filesize);
viewHolder.tv_rankingitemDownload = (TextView) convertView
.findViewById(R.id.ranking_item_download);
viewHolder.imgView_Icon = (ImageView) convertView
.findViewById(R.id.ranking_item_icon);
viewHolder.ranking_item_pb = (ProgressBar) convertView
.findViewById(R.id.ranking_item_pb);
progressbarMax = viewHolder.ranking_item_pb.getMax();
int[] star_id = { R.id.star1, R.id.star2, R.id.star3, R.id.star4,
R.id.star5 };
for (int i = 0; i < viewHolder.imgView_Star.length; i++) {
viewHolder.imgView_Star[i] = (ImageView) convertView
.findViewById(star_id[i]);
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
final ViewHolder vh1 = viewHolder;
// 得到当前下载的被观察者(对应的下载类)
final Observed observed = DownloadManager.getManager().getObserved(
null, new DownloadFile(mRecommendBeans.get(position)), context);
DownloadFile downloadFile = observed.replaceBean();
viewHolder
.setUpdateListener(new com.anjoyo.gamecenter5.loader.ViewHolder.UpdateListener() {
@Override
public void update() {//获得最新状态
DownloadFile downloadFile = observed.replaceBean();
Log.d("update",
"===========.RecommendedAdapter>>>>>>>>>>>>>"
+ downloadFile.appPackageName);
//把最新状态通过handler传递个主线程更新ui
Message msg = ha.obtainMessage();
msg.obj = viewHolder;
msg.arg1 = downloadFile.downloadState;
msg.arg2 = (int) (downloadFile.downloadSize * 1000.0 / downloadFile.fileSize);
ha.sendMessage(msg);
}
});
//把当前观察者viewholder对象注册给被观察者
observed.addObserver(viewHolder);
Log.d("recommend",
"observed" + observed + "===mRecommendBeans.get(position)==="
+ mRecommendBeans.get(position).pachagename);
viewHolder.tv_rankingitemDownload.setTag(position);
final RecommendBean bean = mRecommendBeans.get(position);
for (int i = 0; i < viewHolder.imgView_Star.length; i++) {
viewHolder.imgView_Star[i].setImageResource(R.drawable.star_gray);
}
for (int i = 0, starNum = bean.star; i < starNum; i++) {
viewHolder.imgView_Star[i].setImageResource(R.drawable.star_yellow);
}
viewHolder.tv_rankingitemDownload
.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
TextView tv = (TextView) v;
int index = (Integer) v.getTag();
Log.d("ccc", "TAG = " + index);
Log.d("ccc", "po:" + index);
if (tv.getText().equals("下载")) {
observed.start();
tv.setBackgroundColor(Color
.argb(250, 255, 255, 255));
tv.setTextColor(Color.BLACK);
tv.setText("0.0%");
} else if (((String) tv.getText()).indexOf("%") != -1) {// 存在%时为正在下载
if (observed != null)
observed.pause();
tv.setBackgroundColor(Color
.argb(250, 255, 255, 255));
tv.setTextColor(Color.BLACK);
tv.setText("继续");
} else if (tv.getText().equals("继续")) {
tv.setText("准备中");
observed.start();
} else if (tv.getText().equals("安装")) {
TabDFm_Management.installApk(context,
mRecommendBeans.get(position).flashurl);
} else if (tv.getText().equals("打开"))
TabDFm_Management.startApplitation(context,
mRecommendBeans.get(position).pachagename);
};
});
if (SharedpreferensUitls.getTagGPRS(context) == 1
&& ConnectionUtil.getConnectedType(context) == 0) {
viewHolder.imgView_Icon.setImageResource(R.drawable.imagedefault);
} else {
utils.display(viewHolder.imgView_Icon, bean.icon);
}
changeState(
viewHolder,
downloadFile.downloadState,
(int) (downloadFile.downloadSize * 1000.0 / downloadFile.fileSize));
viewHolder.txtView_Title.setText(Html.fromHtml(bean.title));
viewHolder.txtView_FileSize.setText(bean.filesize);
return convertView;
}
Handler ha = new Handler(Looper.getMainLooper()) {
public void handleMessage(android.os.Message msg) {
ViewHolder viewHolder = (ViewHolder) msg.obj;
int status = msg.arg1;
int progress = msg.arg2;
changeState(viewHolder, status, progress);
};
};
private void changeState(final ViewHolder viewHolder, int status,
int progress) {
// Integer status = downloadFile.downloadState;
if (Cons.LOADING == status) {
viewHolder.tv_rankingitemDownload.setBackgroundColor(Color.argb(
250, 255, 255, 255));
viewHolder.tv_rankingitemDownload.setTextColor(Color.BLACK);
String prg = progress / 10.0 + "";
if (prg.contains("."))
prg = prg.substring(0, prg.indexOf(".") + 2) + "%";
viewHolder.tv_rankingitemDownload.setText(prg);
} else if (Cons.SUSPEND == status) {
viewHolder.tv_rankingitemDownload.setBackgroundColor(Color.argb(
250, 255, 255, 255));
viewHolder.tv_rankingitemDownload.setTextColor(Color.BLACK);
viewHolder.tv_rankingitemDownload.setText("继续");
} else if (Cons.COMPLETE == status) {
viewHolder.tv_rankingitemDownload.setBackgroundColor(Color.argb(
250, 255, 255, 255));
viewHolder.tv_rankingitemDownload.setTextColor(Color.BLACK);
viewHolder.tv_rankingitemDownload.setText("安装");
} else if (Cons.WAITING == status) {
viewHolder.tv_rankingitemDownload.setBackgroundColor(Color.argb(
250, 255, 255, 255));
viewHolder.tv_rankingitemDownload.setTextColor(Color.BLACK);
viewHolder.tv_rankingitemDownload.setText("等待");
} else if (Cons.INSTALLED == status) {
viewHolder.tv_rankingitemDownload.setText("打开");
} else {
viewHolder.tv_rankingitemDownload
.setBackgroundResource(R.drawable.download_normal);
viewHolder.tv_rankingitemDownload.setText("下载");
viewHolder.tv_rankingitemDownload.setTextColor(Color.WHITE);
}
}
//继承观察者Viewholder
class ViewHolder extends com.anjoyo.gamecenter5.loader.ViewHolder {
TextView txtView_Title;
TextView txtView_FileSize;
TextView tv_rankingitemDownload;
ImageView imgView_Icon;
ImageView[] imgView_Star = new ImageView[5];
ProgressBar ranking_item_pb;
}