在学习了javaSE过后,现在开始继续我的android生活,之前学习完JavaSE,通过UI界面做过模拟游戏《贪吃蛇》和基本版计算器,现在学习Android接近有20天的时间,开始制作模拟手机助手下载,制作手机助手下载,关键是练习一下listview,和listview一些相关的优化,以及优化所产生的一些bug和解决。
本次需呀用到hfs外部软件,来解决网络的问题,和一些图片,用于下载时候的显示。例如手机qq、微信、等一些软件,
下载软件的时候需要下载是时间,因为我们的main主线程不能做耗时工作,所以下载的时候需要在子线程里面下载,这边需要用的AsyncTask。AsyncTask中的doInBackground是在子线程中下载,onProgressUpdate、onPostExecute(String)和onPostExecute都是在主线程中操作,onProgressUpdate是在doInBackground中下载一半的时候,想要对主线程进行操作,onPostExecute是要进行下载之前才执行,onPostExecute(String)是下载之后才操作。
doInBackground(String)在下载的过程中我们需要传输下载路径。
下载用到URL,例如:URL url = new URL(imageUrl);刚开始打开软件的时候,一开始显示整个页面布局,和刚开始我们软件的图标,log。都需要下载,下载图片的用到BitmapFactory,例如:Bitmap bitmap=BitmapFactory.decodeStream(openStream);单下载完成后需要在页面中更改,,因为主线程中不能做页面的更改进行一系列的操作,所以需要在doInBackground中将下载好的bitmap return到onPostExecute,在onPostExecute中可以对主线程进行做一系列的操作,image.setImageBitmap(result);这样,一开始的基本页面既可以完成,如图:
这些打开软件的是最基本的显示,图标和数据都来自于网络,每次滑动的时候都会不断的下载图标,下载在过的图标他会再次在下载,这个体验是非常不好的。所以我们在下载的图标过后要把bitmap保存起来,当已经下载过的就不要再下载,直接从容器里面取。例如:Bitmap bitmap = imageBitmaplist.get(position);在图片bitmap 下载完后就保存起来,不过在我们下载的过程中是需要时间的。所以在现在中如果还是快速的上下滑动还是一样会导致图片多次下载,解决:因为我们在每次下载的时候都会new 出asyncTask 来对我们图片进行下载,例如:MyAsyncTask asyncTask = new MyAsyncTask(image,position);所以我们让new 出的asyncTask 进行有条件的执行,把每一行先对应的asyncTask 进行保存。在每次要下在的时候先看一下容器里面的asyncTask 是否存在,如果存在的话说明正在下载,我们就不用再进行对应的下载。例如:
Bitmap bitmap = imageBitmaplist.get(position);
if (bitmap==null) {
MyAsyncTask asyncTask = asyncTasklist.get(position);
if (asyncTask==null) {
asyncTask = new MyAsyncTask(image,position);
asyncTask.execute(imageUrllist.get(position));
asyncTasklist.put(position, asyncTask);
}
} else {
image.setImageBitmap(bitmap);
}
这样子就可以在下载的时候避免多次下载图标。
对listview的优化,在每次上下滑动的时候会每次产生一个新的View。所以要对View进行复用,可以用上一个消失的View convertView,来替换这个所要产生新的view。所以可以对convertView进行判断,如果convertView要是为null 的时候我们才创建一个新的View 。要是不为空的话,就直接拿起来复用,这丫可以解决资源问题,不会造成资源浪费。例如:
View inflate =null;
if (convertView==null) {
LayoutInflater layoutInflater = getLayoutInflater();
inflate = layoutInflater.inflate(R.layout.layout, null);
} else {
inflate=convertView;
}
和View 一样,我们每次有声明的一开始声明的
ImageView image = (ImageView) inflate.findViewById(R.id.image);
ProgressBar progressBar1 = (ProgressBar) inflate.findViewById(R.id.progressBar1);
Button button1 = (Button) inflate.findViewById(R.id.button1);
TextView text = (TextView) inflate.findViewById(R.id.textView1);
几个组件,也可以对其复用。把这些都放在一个class里面需要的时候拿出来用就可以,例如:
View inflate =null;
Myview myview =null;
if (convertView==null) {
myview = new Myview();
LayoutInflater layoutInflater = getLayoutInflater();
inflate = layoutInflater.inflate(R.layout.layout, null);
myview.image = (ImageView) inflate.findViewById(R.id.image);
myview.progressBar1 = (ProgressBar) inflate.findViewById(R.id.progressBar1);
myview.button1 = (Button) inflate.findViewById(R.id.button1);
myview.text = (TextView) inflate.findViewById(R.id.textView1);
inflate.setTag(myview);
} else {
inflate=convertView;
myview=(Myview) inflate.getTag();
}
这样的话可以进行多次复用。;
但是由于复用的关系,在每次图片还在下载的过程是如果图片在第一张下载完成后,后面的图片还没有下载的关系,进行上下的滑动。会发现,在发现在底下的时候有出现第一次的图标,在过了一段时间后会发现图片的跳变问题,这个就是因为view复用,例如第7行复用第0行的时候,第7行的图标还没有下载,原先应该是默认的原始图片,但是由于在第0行的时候已经对图标进行更改,他已经不是默认的图标,所以会显示之前的图标,
解决:在一开始要下载图标,更改图片之前把图片先改为我们默认的图片,例如:
myview.image.setImageResource(R.drawable.ic_launcher);
这样只能解决基本的问题,如果一开始只是轻轻滑动的话,是不会出现图标闪变,如果要是一开始的时候在图片还在下载的时候就进行快速的上下滑动的话,这样还是会出现图片闪跳。我们在轻轻滑动的时候他view 的替换是有规律的,但是如果开始滑动的时候view是没有规律,他的出现时不定像的,即在滑动过程中,要对image进行替换。
例如:
public void changview(ImageView image)
{
this.image = image;
}
asyncTask.changview(myview.image);
并且在下载完图片的时候,必须对当前行有显示的才进行更改。
例如:
int fvp = mlistview.getFirstVisiblePosition();
int lvp = mlistview.getLastVisiblePosition();
if (position>=fvp&&position<=lvp) {
//保存bitmap
imageBitmaplist.put(position, result);
image.setImageBitmap(result);
}
以上是打开界面时候最基本的显示,一切数据都来自与网络,接下来就是当我们点击按钮下载的时候,会进行基本的文件下载,如同之前的图片下载一样,文件下载是在点击下载后文件才会下载,所有操作如同上面图片基本相同,唯一的就是在点击下载的时候,文件的进度条会跟随的下载进度不断的进行促发。这是需要用到的是onProgressUpdate();在用到onProgressUpdate的时候,数据下载进度是从publishProgress传入;操作代码如;
问题:由于一开始的优化,对view,和基本组件的复用关系,导致了bug,在上下滑动的时候别的地方没有点击下载,他的ProgressBar中的进度条也是显示满格。
解决:
如同图片的一样,定义容器,用于保存,保存当前是否是在下载,下载中,下载成功的三个状态,在对齐做对应的操作,并且与进行替换,操作代码如下:
在这次的模拟手机助手下载,已经基本上都完成了。