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


ok 正文:

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


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

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

2、设置layout了,

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


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


2)新建一个单行布局

弄个这样的就好了

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

在progressBar中加这样一句话就好了

  
android:visibility="invisible"


隐藏后效果:


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<Integer, DownLoadThread> mItemLoadThreads;// 用于存放已启动的进度条 ,                                                          // 在点击启动线程的时候设置值    private Map<Integer, DownLoadHandler> mItemLoadHandlers;    private Map<Integer, BarInfo> 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.imageView1);                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<Integer, MainActivity.DownLoadThread>();        mItemProgressInfo = new HashMap<Integer, MainActivity.BarInfo>();        mItemLoadHandlers = new HashMap<Integer, MainActivity.DownLoadHandler>();    }    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;    }}


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

明天说说怎么处理撒。






更多相关文章

  1. 深入理解android消息处理机制
  2. Android开发实践:由new Handler()说开去
  3. Android(安卓)Handler消息机制
  4. Android(安卓)线程 thread 两种实现方法!
  5. Android(安卓)异步消息处理机制 让你深入理解 Looper、Handler、
  6. Android(安卓)IPC之Messenger和AIDL(android开发艺术探索随笔)
  7. Android(安卓)ContentProvider的线程安全(一)
  8. Android中EventBus原理及用法详情
  9. 什么是ANR,如何避免?

随机推荐

  1. 【Android】小白进阶之回调监听机制liste
  2. Activity中的四种启动模式和onNewIntent(
  3. Android联系人数据库全解析-2.0以上
  4. Android 存储目录
  5. Android AudioPolicyService和AudioPolic
  6. Android模拟器——QEMU
  7. Android四种启动模式及其注意事项
  8. 安卓布局被软键盘顶上去的解决方案
  9. ProGuard代码混淆详细攻略
  10. android切换到后台,返回后图片纹理丢失