谷歌应用市场6


1.观察设计模式

1.观察者与被观察者

2.观察进度的改变

3.自己重新定义被观察者,可以多暴露多个方法

(1)被观察者

// 被观察者
//  假设 具备当前的下载进度
public class DownloadManager  {public interface Observer{public void update();public void updateState();}List observers=new ArrayList();// 有内容发生了改变1//  添加观察者public void addObserver(Observer observer){if(observer==null){throw new RuntimeException();}if(!observers.contains(observer)){observers.add(observer);}}// 通知数据发生变化public void notifyObservers(){for(Observer observer:observers){observer.update();}}// 通知状态改变public void notifyState(){for(Observer observer:observers){observer.updateState();}}}


(2)观察者1

// 观察者
public class DetailView  implements Observer {@Overridepublic void update() {System.out.println("aaabbbccc");}@Overridepublic void updateState() {System.out.println("状态发生改变");}}


(3)观察者2

// 观察者
public class DetailView2 implements Observer {//当被观察者数据发生变化的时候 调用该方法@Overridepublic void update(Observable observable, Object data) {System.out.println("爷爷观察到了你的变化");}}


(4)MainActivity

public class MainActivity extends Activity {private DownloadManager downloadManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);downloadManager = new DownloadManager();downloadManager.addObserver(new DetailView()); // 当被观察者 数据发生变化的时候 通知观察者//	downloadManager.addObserver(new DetailView2());//  观察者}	public void click(View v){downloadManager.notifyObservers();// 通知观察者 内容发生变化}
}


 

 

4.项目补充:下载被观察者

public class DownloadManager {/** 默认 */public static final int STATE_NONE = 0;/** 等待 */public static final int STATE_WAITING = 1;/** 下载中 */public static final int STATE_DOWNLOADING = 2;/** 暂停 */public static final int STATE_PAUSE = 3;/** 错误 */public static final int STATE_ERROR = 4;/** 下载完成 */public static final int STATE_DOWNLOED = 5;private static DownloadManager instance;private DownloadManager() {}/** 用于记录下载信息,如果是正式项目,需要持久化保存 */private Map mDownloadMap = new ConcurrentHashMap();/**用于记录所有下载的任务,方便取消下载时,能通过id找到该任务进行删除*/private Map mTaskMap=new ConcurrentHashMap();private List mObservers=new ArrayList();/** 注册观察者 */public void registerObserver(DownloadObserver observer) {synchronized (mObservers) {if (!mObservers.contains(observer)) {mObservers.add(observer);}}}/** 反注册观察者 */public void unRegisterObserver(DownloadObserver observer) {synchronized (mObservers) {if (mObservers.contains(observer)) {mObservers.remove(observer);}}}/** 当下载状态发送改变的时候回调 */public void notifyDownloadStateChanged(DownloadInfo info) {synchronized (mObservers) {for (DownloadObserver observer : mObservers) {observer.onDownloadStateChanged(info);}}}/** 当下载进度发送改变的时候回调 */public void notifyDownloadProgressed(DownloadInfo info) {synchronized (mObservers) {for (DownloadObserver observer : mObservers) {observer.onDownloadProgressed(info);}}}// 单例public static synchronized DownloadManager getInstance() {if (instance == null) {instance = new DownloadManager();}return instance;}public synchronized void download(AppInfo appInfo) {DownloadInfo info = mDownloadMap.get(appInfo.getId());if (info == null) {info = DownloadInfo.clone(appInfo);mDownloadMap.put(appInfo.getId(), info);// 保存到集合中}if (info.getDownloadState() == STATE_NONE|| info.getDownloadState() == STATE_PAUSE|| info.getDownloadState() == STATE_ERROR) {// 下载之前,把状态设置为STATE_WAITING,// 因为此时并没有产开始下载,只是把任务放入了线程池中,// 当任务真正开始执行时,才会改为STATE_DOWNLOADINGinfo.setDownloadState(STATE_WAITING);// 通知更新界面 notifyDownloadStateChanged(info);DownloadTask task = new DownloadTask(info);mTaskMap.put(info.getId(), task);ThreadManager.creatDownLoadPool().execute(task);}}/** 安装应用 */public synchronized void install(AppInfo appInfo) {stopDownload(appInfo);DownloadInfo info = mDownloadMap.get(appInfo.getId());// 找出下载信息if (info != null) {// 发送安装的意图Intent installIntent = new Intent(Intent.ACTION_VIEW);installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);installIntent.setDataAndType(Uri.parse("file://" + info.getPath()),"application/vnd.android.package-archive");UIUtils.getContext().startActivity(installIntent);}notifyDownloadStateChanged(info);}/**暂停下载*/public synchronized void pause(AppInfo appInfo){stopDownload(appInfo);DownloadInfo info=mDownloadMap.get(appInfo.getId());if(info!=null){// 修改下载状态info.setDownloadState(STATE_PAUSE);notifyDownloadStateChanged(info);}}/** 取消下载,逻辑和暂停类似,只是需要删除已下载的文件 */public synchronized void cancel(AppInfo appInfo) {stopDownload(appInfo);DownloadInfo info = mDownloadMap.get(appInfo.getId());// 找出下载信息if (info != null) {// 修改下载状态并删除文件info.setDownloadState(STATE_NONE);notifyDownloadStateChanged(info);info.setCurrentSize(0);File file = new File(info.getPath());file.delete();}}private void stopDownload(AppInfo appInfo) {DownloadTask task=mTaskMap.remove(appInfo.getId());if(task!=null){ThreadManager.creatDownLoadPool().cancel(task);}}public class DownloadTask implements Runnable {private DownloadInfo info;public DownloadTask(DownloadInfo info) {this.info = info;}@Overridepublic void run() {info.setDownloadState(STATE_DOWNLOADING);notifyDownloadStateChanged(info);File file = new File(info.getPath());// 获取下载文件HttpResult httpResult = null;InputStream stream = null;// 如果文件不存在, 或者进度为0,或者进度和文件长度不一致 重新下载if (info.getCurrentSize() == 0 || !file.exists()|| file.length() != info.getCurrentSize()) {info.setCurrentSize(0);file.delete();httpResult = HttpHelper.download(HttpHelper.URL+ "download?name=" + info.getUrl());} else {// 不需要重新下载// 文件存在且长度和进度相等,采用断点下载httpResult = HttpHelper.download(HttpHelper.URL+ "download?name=" + info.getUrl() + "&range="+ info.getCurrentSize());}if (httpResult == null|| (stream = httpResult.getInputStream()) == null) {info.setDownloadState(STATE_ERROR);notifyDownloadStateChanged(info);} else {FileOutputStream fos = null;try {fos = new FileOutputStream(file, true);int count = -1;byte[] buffer = new byte[1024];while (((count = stream.read(buffer)) != -1)&& info.getDownloadState() == STATE_DOWNLOADING) {fos.write(buffer, 0, count);fos.flush();info.setCurrentSize(info.getCurrentSize()+count);notifyDownloadProgressed(info);}} catch (Exception e) {LogUtils.e(e);// 出异常后需要修改状态并删除文件info.setDownloadState(STATE_ERROR);notifyDownloadStateChanged(info);info.setCurrentSize(0);file.delete(); } finally {IOUtils.close(fos);if (httpResult != null) {httpResult.close();}}// 判断进度是否和App相等if (info.getCurrentSize() == info.getAppSize()) {info.setDownloadState(STATE_DOWNLOED);notifyDownloadStateChanged(info);} else if (info.getDownloadState() == STATE_PAUSE) {notifyDownloadStateChanged(info);} else {info.setDownloadState(STATE_ERROR);notifyDownloadStateChanged(info);info.setCurrentSize(0);file.delete();}}mTaskMap.remove(info.getId());}}public interface DownloadObserver {public void onDownloadStateChanged(DownloadInfo info);public void onDownloadProgressed(DownloadInfo info);}public DownloadInfo getDownloadInfo(long id) {// TODO Auto-generated method stubreturn mDownloadMap.get(id);}
}


 

 

 

2.总结

1.详情见PPT和完整代码

2.自定义圆形进度条

   框架

public class ProgressView extends View {public ProgressView(Context context) {super(context);}public ProgressView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public ProgressView(Context context, AttributeSet attrs) {super(context, attrs);}// 绘制控件@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//canvas.drawBitmap(bitmap, left, top, paint);   把图片画进去,背景图片/*oval  圆的模型 矩形* startAngle 开始的角度* sweepAngle  范围的角度     //不停修改这个* useCenter  是否填充中间部分* paint   画笔*///canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint);}
}


3.完整代码

public class ProgressArc extends View {private final static int START_PROGRESS = -90;private static final int SET_PROGRESS_END_TIME = 1000;private static final float RATIO = 360f;public final static int PROGRESS_STYLE_NO_PROGRESS = -1;public final static int PROGRESS_STYLE_DOWNLOADING = 0;public final static int PROGRESS_STYLE_WAITING = 1;private int mDrawableForegroudResId;private Drawable mDrawableForegroud;//图片private int mProgressColor;//进度条的颜色private RectF mArcRect;//用于画圆形的区域private Paint mPaint;//用户画进度条的画笔private boolean mUserCenter = false;private OnProgressChangeListener mProgressChangeListener;//进度改变的监听private float mStartProgress;//动画的起始进度private float mCurrentProgress;//当前进度private float mProgress;//目标进度private float mSweep;private long mStartTime, mEndTime;private int mStyle = PROGRESS_STYLE_NO_PROGRESS;private int mArcDiameter;public ProgressArc(Context context) {super(context);int strokeWidth = UIUtils.dip2px(1);mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(strokeWidth);mUserCenter = false;mArcRect = new RectF();}public void setProgressChangeListener(OnProgressChangeListener listener) {mProgressChangeListener = listener;}public void seForegroundResource(int resId) {if (mDrawableForegroudResId == resId) {return;}mDrawableForegroudResId = resId;mDrawableForegroud = UIUtils.getDrawable(mDrawableForegroudResId);invalidateSafe();}/** 设置直径 */public void setArcDiameter(int diameter) {mArcDiameter = diameter;}/** 设置进度条的颜色 */public void setProgressColor(int progressColor) {mProgressColor = progressColor;mPaint.setColor(progressColor);}public void setStyle(int style) {this.mStyle = style;if (mStyle == PROGRESS_STYLE_WAITING) {invalidateSafe();} else {}}/** 设置进度,第二个参数是否采用平滑进度 */public void setProgress(float progress, boolean smooth) {mProgress = progress;if (mProgress == 0) {mCurrentProgress = 0;}mStartProgress = mCurrentProgress;mStartTime = System.currentTimeMillis();if (smooth) {mEndTime = SET_PROGRESS_END_TIME;} else {mEndTime = 0;}invalidateSafe();}private void invalidateSafe() {if (UIUtils.isRunInMainThread()) {postInvalidate();} else {invalidate();}}/** 测量 */protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width = 0;int height = 0;int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);if (widthMode == MeasureSpec.EXACTLY) {//如果是精确的width = widthSize;} else {//采用图片的大小width = mDrawableForegroud == null ? 0 : mDrawableForegroud.getIntrinsicWidth();if (widthMode == MeasureSpec.AT_MOST) {width = Math.min(width, widthSize);}}if (heightMode == MeasureSpec.EXACTLY) {//如果是精确的height = heightSize;} else {//采用图片的大小height = mDrawableForegroud == null ? 0 : mDrawableForegroud.getIntrinsicHeight();if (heightMode == MeasureSpec.AT_MOST) {height = Math.min(height, heightSize);}}//计算出进度条的区域mArcRect.left = (width - mArcDiameter) * 0.5f;mArcRect.top = (height - mArcDiameter) * 0.5f;mArcRect.right = (width + mArcDiameter) * 0.5f;mArcRect.bottom = (height + mArcDiameter) * 0.5f;setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas) {if (mDrawableForegroud != null) {//先把图片画出来mDrawableForegroud.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());mDrawableForegroud.draw(canvas);}//再画进度drawArc(canvas);}protected void drawArc(Canvas canvas) {if (mStyle == PROGRESS_STYLE_DOWNLOADING || mStyle == PROGRESS_STYLE_WAITING) {float factor;long currentTime = System.currentTimeMillis();if (mProgress == 100) {factor = 1;} else {if (currentTime - mStartTime < 0) {factor = 0;} else if (currentTime - mStartTime > mEndTime) {factor = 1;} else {factor = (currentTime - mStartTime) / (float) mEndTime;}}mPaint.setColor(mProgressColor);mCurrentProgress = mStartProgress + factor * (mProgress - mStartProgress);mSweep = mCurrentProgress * RATIO;canvas.drawArc(mArcRect, START_PROGRESS, mSweep, mUserCenter, mPaint);if (factor != 1 && mStyle == PROGRESS_STYLE_DOWNLOADING) {invalidate();}if (mCurrentProgress > 0) {notifyProgressChanged(mCurrentProgress);}}}private void notifyProgressChanged(float currentProgress) {if (mProgressChangeListener != null) {mProgressChangeListener.onProgressChange(currentProgress);}}public static interface OnProgressChangeListener {public void onProgressChange(float smoothProgress);}
}


 

 

4.应用详情内的进度条修改样式





 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

补充

1.收藏下载分享

(1)界面


 

(2)progress_drawable 图层


 

2.DownloadManager

public class DownloadManager {/** 默认 */public static final int STATE_NONE = 0;/** 等待 */public static final int STATE_WAITING = 1;/** 下载中 */public static final int STATE_DOWNLOADING = 2;/** 暂停 */public static final int STATE_PAUSE = 3;/** 错误 */public static final int STATE_ERROR = 4;/** 下载完成 */public static final int STATE_DOWNLOED = 5;private static DownloadManager instance;private DownloadManager() {}/** 用于记录下载信息,如果是正式项目,需要持久化保存 */private Map mDownloadMap = new ConcurrentHashMap();/**用于记录所有下载的任务,方便取消下载时,能通过id找到该任务进行删除*/private Map mTaskMap=new ConcurrentHashMap();private List mObservers=new ArrayList();/** 注册观察者 */public void registerObserver(DownloadObserver observer) {synchronized (mObservers) {if (!mObservers.contains(observer)) {mObservers.add(observer);}}}/** 反注册观察者 */public void unRegisterObserver(DownloadObserver observer) {synchronized (mObservers) {if (mObservers.contains(observer)) {mObservers.remove(observer);}}}/** 当下载状态发送改变的时候回调 */public void notifyDownloadStateChanged(DownloadInfo info) {synchronized (mObservers) {for (DownloadObserver observer : mObservers) {observer.onDownloadStateChanged(info);}}}/** 当下载进度发送改变的时候回调 */public void notifyDownloadProgressed(DownloadInfo info) {synchronized (mObservers) {for (DownloadObserver observer : mObservers) {observer.onDownloadProgressed(info);}}}// 单例public static synchronized DownloadManager getInstance() {if (instance == null) {instance = new DownloadManager();}return instance;}public synchronized void download(AppInfo appInfo) {DownloadInfo info = mDownloadMap.get(appInfo.getId());if (info == null) {info = DownloadInfo.clone(appInfo);mDownloadMap.put(appInfo.getId(), info);// 保存到集合中}if (info.getDownloadState() == STATE_NONE|| info.getDownloadState() == STATE_PAUSE|| info.getDownloadState() == STATE_ERROR) {// 下载之前,把状态设置为STATE_WAITING,// 因为此时并没有产开始下载,只是把任务放入了线程池中,// 当任务真正开始执行时,才会改为STATE_DOWNLOADINGinfo.setDownloadState(STATE_WAITING);// 通知更新界面 notifyDownloadStateChanged(info);DownloadTask task = new DownloadTask(info);mTaskMap.put(info.getId(), task);ThreadManager.creatDownLoadPool().execute(task);}}/** 安装应用 */public synchronized void install(AppInfo appInfo) {stopDownload(appInfo);DownloadInfo info = mDownloadMap.get(appInfo.getId());// 找出下载信息if (info != null) {// 发送安装的意图Intent installIntent = new Intent(Intent.ACTION_VIEW);installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);installIntent.setDataAndType(Uri.parse("file://" + info.getPath()),"application/vnd.android.package-archive");UIUtils.getContext().startActivity(installIntent);}notifyDownloadStateChanged(info);}/**暂停下载*/public synchronized void pause(AppInfo appInfo){stopDownload(appInfo);DownloadInfo info=mDownloadMap.get(appInfo.getId());if(info!=null){// 修改下载状态info.setDownloadState(STATE_PAUSE);notifyDownloadStateChanged(info);}}/** 取消下载,逻辑和暂停类似,只是需要删除已下载的文件 */public synchronized void cancel(AppInfo appInfo) {stopDownload(appInfo);DownloadInfo info = mDownloadMap.get(appInfo.getId());// 找出下载信息if (info != null) {// 修改下载状态并删除文件info.setDownloadState(STATE_NONE);notifyDownloadStateChanged(info);info.setCurrentSize(0);File file = new File(info.getPath());file.delete();}}private void stopDownload(AppInfo appInfo) {DownloadTask task=mTaskMap.remove(appInfo.getId());if(task!=null){ThreadManager.creatDownLoadPool().cancel(task);}}public class DownloadTask implements Runnable {private DownloadInfo info;public DownloadTask(DownloadInfo info) {this.info = info;}@Overridepublic void run() {info.setDownloadState(STATE_DOWNLOADING);notifyDownloadStateChanged(info);File file = new File(info.getPath());// 获取下载文件HttpResult httpResult = null;InputStream stream = null;// 如果文件不存在, 或者进度为0,或者进度和文件长度不一致 重新下载if (info.getCurrentSize() == 0 || !file.exists()|| file.length() != info.getCurrentSize()) {info.setCurrentSize(0);file.delete();httpResult = HttpHelper.download(HttpHelper.URL+ "download?name=" + info.getUrl());} else {// 不需要重新下载// 文件存在且长度和进度相等,采用断点下载httpResult = HttpHelper.download(HttpHelper.URL+ "download?name=" + info.getUrl() + "&range="+ info.getCurrentSize());}if (httpResult == null|| (stream = httpResult.getInputStream()) == null) {info.setDownloadState(STATE_ERROR);notifyDownloadStateChanged(info);} else {FileOutputStream fos = null;try {fos = new FileOutputStream(file, true);int count = -1;byte[] buffer = new byte[1024];while (((count = stream.read(buffer)) != -1)&& info.getDownloadState() == STATE_DOWNLOADING) {fos.write(buffer, 0, count);fos.flush();info.setCurrentSize(info.getCurrentSize()+count);notifyDownloadProgressed(info);}} catch (Exception e) {LogUtils.e(e);// 出异常后需要修改状态并删除文件info.setDownloadState(STATE_ERROR);notifyDownloadStateChanged(info);info.setCurrentSize(0);file.delete(); } finally {IOUtils.close(fos);if (httpResult != null) {httpResult.close();}}// 判断进度是否和App相等if (info.getCurrentSize() == info.getAppSize()) {info.setDownloadState(STATE_DOWNLOED);notifyDownloadStateChanged(info);} else if (info.getDownloadState() == STATE_PAUSE) {notifyDownloadStateChanged(info);} else {info.setDownloadState(STATE_ERROR);notifyDownloadStateChanged(info);info.setCurrentSize(0);file.delete();}}mTaskMap.remove(info.getId());}}public interface DownloadObserver {public void onDownloadStateChanged(DownloadInfo info);public void onDownloadProgressed(DownloadInfo info);}public DownloadInfo getDownloadInfo(long id) {// TODO Auto-generated method stubreturn mDownloadMap.get(id);}
}


 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部