java 多线程 listview,android 多线程同时下载多个较大文件

先说声 sorry 不好意思 拖了 两三天了。。。。

ok 正文:

额 开始做程序前 先把要测试的服务器和文件准备好撒~

1、配置AndroidManifest.xml,既然是要向本地sdcard 写内容,访问URL 权限是必须滴

2、设置layout了,

1)在activity_main.xml中加入一个listView,加入listView的要注意啊

android:layout_height="match_parent"这个参数一定得是match_parent的

2)新建一个单行布局

弄个这样的就好了

b7604da6864dcf3aa46a9dededf72d2b.png

注意 没开始下载时 那个进度条 应该隐藏的

在progressBar中加这样一句话就好了android:visibility="invisible"

隐藏后效果:

b965b7231deecdf2b4290d029552b6cf.png

3、写代码:package com.example.bolg_download_file;

import java.io.File;

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 java.util.HashMap;

import java.util.List;

import java.util.Map;

import android.os.Bundle;

import android.os.Environment;

import android.os.Handler;

import android.os.Message;

import android.app.Activity;

import android.content.ClipData.Item;

import android.view.Menu;

import android.view.View;

import android.view.ViewGroup;

import android.view.View.OnClickListener;

import android.widget.BaseAdapter;

import android.widget.Button;

import android.widget.ImageView;

import android.widget.ListView;

import android.widget.ProgressBar;

import android.widget.TextView;

import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener

{

private ListView mListView;

private DownLoadAdapter mAdapter;

private Map mItemLoadThreads;// 用于存放已启动的进度条 ,

// 在点击启动线程的时候设置值

private Map mItemLoadHandlers;

private Map mItemProgressInfo;// 用于存放所有进度条的信息,在创建bar的时候就要设置值了

class ViewHolder

{

ImageView mImageView;

TextView mTitle;

TextView mSubtitle;

Button mButton;

ProgressBar mBar;

}

class BarInfo

{ // 用来分装 Bar(进度条)的信息

boolean isDownLoad;// 是否已经下载,这个参数

// 我暂时没有使用,但是想要将下载系统做的更完善,应该是需要它的,大家可以完善下~嘿嘿

boolean visible;// bar是否显示

int currentProgress;// 进度条当前的值

int maxProgress;// 进度条的最大值

}

class DownLoadHandler extends Handler

{

private ProgressBar bar;

public void setBar(ProgressBar bar)

{

this.bar = bar;

}

@Override

public void handleMessage(Message msg)

{

BarInfo bi = (BarInfo) msg.obj;

bar.setVisibility(View.VISIBLE);

bar.setMax(bi.maxProgress);

bar.setProgress(bi.currentProgress);

}

}

class DownLoadAdapter extends BaseAdapter

{

@Override

public View getView(int position, View convertView, ViewGroup parent)

{

/*

* 前面做 ListView优化时 有说过现在再说一下撒 主要参数: position:代表ListView的当前行号,

* convertView:代表ListView的缓存layout

*/

View layout = null;

ViewHolder holder = null;

if (convertView == null)

{

layout = getLayoutInflater().inflate(R.layout.list_item, null);

holder = new ViewHolder();

holder.mBar = (ProgressBar) layout

.findViewById(R.id.progressBar1);

holder.mImageView = (ImageView) layout

.findViewById(R.id.p_w_picpathView1);

holder.mTitle = (TextView) layout.findViewById(R.id.textView1);

holder.mSubtitle = (TextView) layout

.findViewById(R.id.textView2);

holder.mButton = (Button) layout.findViewById(R.id.button1);

holder.mButton.setTag(position);// 将当前行号 给button

holder.mButton.setOnClickListener(MainActivity.this);// 设置点击事件

layout.setTag(holder);

}

else

{

layout = convertView;

holder = (ViewHolder) layout.getTag();

}

// 设置控件内容

DownLoadHandler dlh = null;

if (!mItemLoadHandlers.containsKey(position))

{// 给每一行分配一个handler

dlh = new DownLoadHandler();

mItemLoadHandlers.put(position, dlh);

dlh.setBar(holder.mBar);

}

else

{

dlh = mItemLoadHandlers.get(position);

dlh.setBar(holder.mBar);

}

if (!mItemProgressInfo.containsKey(position))

{// 设置 BarInfo 如果当前行已经存在就不用设置了

BarInfo value = new BarInfo();

value.currentProgress = 0;

value.isDownLoad = false;

value.maxProgress = 0;

value.visible = false;

mItemProgressInfo.put(position, value);

}

holder.mTitle.setText("title:" + position);

BarInfo bi = mItemProgressInfo.get(position);

if (bi.visible)

{

holder.mBar.setVisibility(View.VISIBLE);

}

else

{

holder.mBar.setVisibility(View.INVISIBLE);

}

holder.mBar.setMax(bi.maxProgress);

holder.mBar.setProgress(bi.currentProgress);

return layout;

}

@Override

public int getCount()

{

// 目前先把他写死了,我服务器提供了 15个下载文件了

return 9;

}

@Override

public Object getItem(int position)

{

return null;

}

@Override

public long getItemId(int position)

{

return 0;

}

}

@Override

public void onClick(View v)// 这里的view 是触发事件的空间

{

int position = (Integer) v.getTag();

BarInfo bi = mItemProgressInfo.get(position);

if (!mItemLoadThreads.containsKey(position))

{// 判断当前行是否已启动了线程,如果没启动就启动一个线程执行下载功能

// 因为前面 在做list_item的时候将progressbar的显示调成隐藏的了,这里得把他弄出来撒

DownLoadThread dt = new DownLoadThread(position);

dt.start();

mItemLoadThreads.put(position, dt);

}

else

// 如果已经启动了就 通知用户 该软件正在下载

{

Toast.makeText(MainActivity.this, "该文件正在下载。。。请稍后撒~~~",

Toast.LENGTH_SHORT).show();

// toast的最后一个参数代表Toast的显示时间:

// 主要有两个值:LENGTH_SHOT表示 较短时间

// LENGTH_LONG表示 较长时间

}

}

private final static String NET_WORK_PATH = "http://10.0.2.2:8080/download/";// 前面有说过这里为什么是10.0.2.2

class DownLoadThread extends Thread

{

int position;

public DownLoadThread(int position)

{

this.position = position;

}

@Override

public void run()

{

InputStream is = null;

OutputStream os = null;

try

{

BarInfo bi = mItemProgressInfo.get(position);

String fileName = "abc" + position + ".zip";

File file = Environment.getExternalStorageDirectory();

os = new FileOutputStream(file.getAbsoluteFile() + "/"

+ fileName);

URL u = new URL(NET_WORK_PATH + fileName);// 这里写这么长只是构造文件名而已不用过多纠结撒

URLConnection urlConn = u.openConnection();

bi.maxProgress = urlConn.getContentLength();// 获取文件大小;要注意这里的文件大小单位是字节,所以文件过大的话

// 最好用long类型的了

is = urlConn.getInputStream();

byte[] buffer = new byte[1024];

int len = 0;

int sum = 0;

bi.visible = true;

while (-1 != (len = is.read(buffer)))

{

sum += len;

Message msg = new Message();

bi.currentProgress = sum;

os.write(buffer);

msg.arg1 = position;

msg.obj = bi;

mItemLoadHandlers.get(position).sendMessage(msg);

}

os.flush();// 嘿嘿 下载完后 java 的io要flush一下输出流的缓存的,上回我没写哦,不知道大家

// 有没有发现这个错误撒 嘿嘿~

// 下载完后 做一些 数据的更改撒

bi.visible = false;

}

catch (MalformedURLException e)

{

e.printStackTrace();

}

catch (IOException e)

{

e.printStackTrace();

}

}

}

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

initUi();

initData();

}

private void initData()

{

mItemLoadThreads = new HashMap();

mItemProgressInfo = new HashMap();

mItemLoadHandlers = new HashMap();

}

private void initUi()

{

mListView = (ListView) findViewById(R.id.listView1);

mAdapter = new DownLoadAdapter();

mListView.setAdapter(mAdapter);

}

@Override

public boolean onCreateOptionsMenu(Menu menu)

{

getMenuInflater().inflate(R.menu.main, menu);

return true;

}

}

今天的代码 有些多撒 正常下载是没有问题的 这篇的代码 存在一个问题 那就是会跳行,嘿嘿 留给大家这个问题了,

明天说说怎么处理撒。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值