Android多线程+单线程+断点续传+进度条显示下载功能

效果图

白话分析:

多线程:肯定是多个线程咯

断点:线程停止下载的位置

续传:线程从停止下载的位置上继续下载,直到完成任务为止。

核心分析:

断点:

当前线程已经下载的数据长度

续传:

向服务器请求上次线程停止下载位置的数据

con.setRequestProperty("Range", "bytes=" + start + "-" + end);

分配线程:

 int currentPartSize = fileSize / mThreadNum;

定义位置

定义线程开始下载的位置和结束的位置

for (int i = 0; i < mThreadNum; i++) {
int start = i * currentPartSize;//计算每条线程下载的开始位置
 int end = start + currentPartSize-1;//线程结束的位置
 if(i==mThreadNum-1){
   end=fileSize;
  }}

创建数据库:

由于每一个文件要分成多个部分,要被不同的线程同时进行下载。当然要创建线程表,保存当前线程下载开始的位置和结束的位置,还有完成进度等。创建file表,保存当前下载的文件信息,比如:文件名,url,下载进度等信息
线程表:

public static final String CREATE_TABLE_SQL="create table "+TABLE_NAME+"(_id integer primary "
      +"key autoincrement, threadId, start , end, completed, url)";

file表:

public static final String CREATE_TABLE_SQL="create table "+TABLE_NAME+"(_id integer primary" +
    " key autoincrement ,fileName, url, length, finished)";

创建线程类

无非就2个类,一个是线程管理类DownLoadManager.Java,核心方法:start(),stop(),restart(),addTask().clear()。另一个是线程任务类

DownLoadTask.java,就是一个线程类,用于下载线程分配好的任务。后面会贴出具体代码。

创建数据库方法类

无非就是单例模式,封装一些增删改查等基础数据库方法,后面会贴出具体代码。

创建实体类

也就是创建ThreadInfo和FileInfo这2个实体类,把下载文件信息和线程信息暂时存储起来。

引入的第三方开源库

NumberProgressBar是一个关于进度条的开源库,挺不错的。直达链接

代码具体分析

1.首先是创建实体类,文件的实体类FileInfo,肯定有fileName,url,length,finised,isStop,isDownloading这些属性。线程的实体类ThreadInfo肯定有threadId,start,end,completed,url这些属性。这些都很简单

 //ThredInfo.java
  public class FileInfo {
  private String fileName; //文件名
  private String url; //下载地址
  private int length; //文件大小
  private int finished; //下载已完成进度
  private boolean isStop=false; //是否暂停下载
  private boolean isDownloading=false; //是否正在下载
  public FileInfo(){
  }
  public FileInfo(String fileName,String url){
    this.fileName=fileName;
    this.url=url;
  }
  public String getFileName() {
    return fileName;
  }
  public void setFileName(String fileName) {
    this.fileName = fileName;
  }
  public String getUrl() {
    return url;
  }
  public void setUrl(String url) {
    this.url = url;
  }
  public int getLength() {
    return length;
  }
  public void setLength(int length) {
    this.length = length;
  }
  public int getFinished() {
    return finished;
  }
  public void setFinished(int finished) {
    this.finished = finished;
  }
  public boolean isStop() {
    return isStop;
  }
  public void setStop(boolean stop) {
    isStop = stop;
  }
  public boolean isDownloading() {
    return isDownloading;
  }
  public void setDownloading(boolean downloading) {
    isDownloading = downloading;
  }
  @Override
  public String toString() {
    return "FileInfo{" +
        "fileName='" + fileName + '\'' +
        ", url='" + url + '\'' +
        ", length=" + length +
        ", finished=" + finished +
        ", isStop=" + isStop +
        ", isDownloading=" + isDownloading +
        '}';
  }}
 //FileInfo.java
  public class FileInfo {
  private String fileName; //文件名
  private String url; //下载地址
  private int length; //文件大小
  private int finished; //下载已完成进度
  private boolean isStop=false; //是否暂停下载
  private boolean isDownloading=false; //是否正在下载
  public FileInfo(){
  }
  public FileInfo(String fileName,String url){
    this.fileName=fileName;
    this.url=url;
  }
  public String getFileName() {
    return fileName;
  }
  public void setFileName(String fileName) {
    this.fileName = fileName;
  }
  public String getUrl() {
    return url;
  }
  public void setUrl(String url) {
    this.url = url;
  }
  public int getLength() {
    return length;
  }
  public void setLength(int length) {
    this.length = length;
  }
  public int getFinished() {
    return finished;
  }
  public void setFinished(int finished) {
    this.finished = finished;
  }
  public boolean isStop() {
    return isStop;
  }
  public void setStop(boolean stop) {
    isStop = stop;
  }
  public boolean isDownloading() {
    return isDownloading;
  }
  public void setDownloading(boolean downloading) {
    isDownloading = downloading;
  }
  @Override
  public String toString() {
    return "FileInfo{" +
        "fileName='" + fileName + '\'' +
        ", url='" + url + '\'' +
        ", length=" + length +
        ", finished=" + finished +
        ", isStop=" + isStop +
        ", isDownloading=" + isDownloading +
        '}';
  }}

2.实体类写完了,那么接下来写创建一个类,继承SQLiteOpenHelper类,来管理数据库连接,主要作用:管理数据库的初始化,并允许应用程序通过该类获取SQLiteDatabase对象。

 public class ThreadHelper extends SQLiteOpenHelper{
  public static final String TABLE_NAME="downthread";
  public static final String CREATE_TABLE_SQL="create table "+TABLE_NAME+"(_id integer primary "
      +"key autoincrement, threadId, start , end, completed, url)";
  public ThreadHelper(Context context, String name, int version) {
    super(context, name, null, version);
  }
  @Override
  public void onCreate(SQLiteDatabase db) {
    db.execSQL(CREATE_TABLE_SQL);
  }
  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  }}

3.接下来封装一些数据库的增删改查操作,用的单例模式,用双重检验锁实现单例。好处:既能很大程度上确保线程安全,又能实现延迟加载。 缺点:使用volatile关键字会使JVM对该代码的优化丧失,影响性能。并且在一些高并发的情况,仍然可能会创建多个实例,这称为双重检验锁定失效。单例模式

 public class Thread {
  private SQLiteDatabase db;
  public static final String DB_NAME="downthread.db3";
  public static final int VERSION=1;
  private Context mContext;
  private volatile static Thread t=null;
  private Thread(){
    mContext= BaseApplication.getContext();
    db=new ThreadHelper(mContext,DB_NAME,VERSION).getReadableDatabase();
  }
  public static Thread getInstance(){
    if(t==null){
      synchronized (Thread.class){
        if(t==null){
          t=new Thread();
        }
      }
    }
    return t;
  }
  public SQLiteDatabase getDb(){
    return db;
  }
  //保存当前线程下载进度
  public synchronized void insert(ThreadInfo threadInfo){
    ContentValues values=new ContentValues();
    values.put("threadId",threadInfo.getThreadId());
    values.put("start",threadInfo.getStart());
    values.put("end",threadInfo.getEnd());
    values.put("completed",threadInfo.getCompeleted());
    values.put("url",threadInfo.getUrl());
    long rowId=db.insert(ThreadHelper.TABLE_NAME,null,values);
    if(rowId!=-1){
      UtilsLog.i("插入线程记录成功");
    }else{
      UtilsLog.i("插入线程记录失败");
    }
  }
  //查询当前线程 下载的进度
  public synchronized ThreadInfo query(String threadId,String queryUrl){
    Cursor cursor=db.query(ThreadHelper.TABLE_NAME,null,"threadId= ? and url= ?",new String[]{threadId,queryUrl},null,null,null);
    ThreadInfo info=new ThreadInfo();
    if(cursor!=null){
      while (cursor.moveToNext()){
        int start=cursor.getInt(2);
        int end=cursor.getInt(3);
        int completed=cursor.getInt(4);
        String url=cursor.getString(5);
        info.setThreadId(threadId);
        info.setStart(start);
        info.setEnd(end);
        info.setCompeleted(completed);
        info.setUrl(url);
      }
      cursor.close();
    }
    return info;
  }
  //更新当前线程下载进度
  public synchronized void update(ThreadInfo info){
    ContentValues values=new ContentValues();
    values.put("start",info.getStart());
    values.put("completed",info.getCompeleted());
    db.update(ThreadHelper.TABLE_NAME,values,"threadId= ? and url= ?",new String[]{info.getThreadId(),info.getUrl()});
  }
  //关闭db
  public void close(){
    db.close();
  }
  //判断多线程任务下载 是否第一次创建线程
  public boolean isExist(String url){
    Cursor cursor=db.query(ThreadHelper.TABLE_NAME,null,"url= ?",new String[]{url},null,null,null);
    boolean isExist=cursor.moveToNext();
    cursor.close();
    return isExist;
  }
  public synchronized void delete(ThreadInfo info){
    long rowId=db.delete(ThreadHelper.TABLE_NAME,"url =? and threadId= ?",new String[]{info.getUrl(),info.getThreadId()});
    if(rowId!=-1){
      UtilsLog.i("删除下载线程记录成功");
    }else{
      UtilsLog.i("删除下载线程记录失败");
    }
  }
  public synchronized void delete(String url){
    long rowId=db.delete(ThreadHelper.TABLE_NAME,"url =? ",new String[]{url});
    if(rowId!=-1){
      UtilsLog.i("删除下载线程记录成功");
    }else{
      UtilsLog.i("删除下载线程记录失败");
    }
  }}

4.基本的准备操作我们已经完成了,那么开始写关于下载的类吧。首先写的肯定是DownLoadManager类,就是管理任务下载的类。不多说,直接看代码。

public class DownLoadManager {
  private Map<String, FileInfo> map = new HashMap<>();
  private static int mThreadNum;
  private int fileSize;
  private boolean flag = false; //true第一次下载 false不是第一次下载
  private List<DownLoadTask> threads;
  private static FileInfo mInfo;
  private static ResultListener mlistener;
  public static ExecutorService executorService = Executors.newCachedThreadPool();
  public static File file;
  private int totalComleted;
  private DownLoadManager() {
    threads = new ArrayList<>();
  }
  public static DownLoadManager getInstance(FileInfo info, int threadNum,ResultListener listener) {
    mlistener = listener;
    mThreadNum = threadNum;
    mInfo = info;
    return DownLoadManagerHolder.dlm;
  }
  private static class DownLoadManagerHolder {
    private static final DownLoadManager dlm = new DownLoadManager();
  }
  public void start() {
    totalComleted=0;
    clear();
    final FileInfo newInfo = DownLoad.getInstance().queryData(mInfo.getUrl());
    newInfo.setDownloading(true);
    map.put(mInfo.getUrl(),newInfo);
    prepare(newInfo);
  }
  //停止下载任务
  public void stop() {
    map.get(mInfo.getUrl()).setDownloading(false);
    map.get(mInfo.getUrl()).setStop(true);
  }
  public void clear(){
    if(threads.size()>0){
      threads.clear();
    }
  }
  //重新下载任务
  public void restart() {
    stop();
    try {
      File file = new File(com.cmazxiaoma.downloader.download.DownLoadManager.FILE_PATH, map.get(mInfo.getUrl()).getFileName());
      if (file.exists()) {
        file.delete();
      }
      java.lang.Thread.sleep(100);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    DownLoad.getInstance().resetData(mInfo.getUrl());
    start();
  }
  //获取当前任务状态, 是否在下载
  public boolean getCurrentState() {
    return map.get(mInfo.getUrl()).isDownloading();
  }
  //添加下载任务
  public void addTask(FileInfo info) {
    //判断数据库是否已经存在此下载信息
    if (!DownLoad.getInstance().isExist(info)) {
      DownLoad.getInstance().insertData(info);
      map.put(info.getUrl(), info);
    } else {
      DownLoad.getInstance().delete(info);
      DownLoad.getInstance().insertData(info);
      UtilsLog.i("map已经更新");
      map.remove(info.getUrl());
      map.put(info.getUrl(), info);
    }
  }
  private void prepare(final FileInfo newInfo) {
    new java.lang.Thread(){
      @Override
      public void run() {
        HttpURLConnection con = null;
        RandomAccessFile raf=null;
        try {
          //连接资源
          URL url = new URL(newInfo.getUrl());
          UtilsLog.i("url=" + url);
          con = (HttpURLConnection) url.openConnection();
          con.setConnectTimeout(2 * 1000);
          con.setRequestMethod("GET");
          int length = -1;
          UtilsLog.i("responseCode=" + con.getResponseCode());
          if (con.getResponseCode() == 200) {
            length = con.getContentLength();
            UtilsLog.i("文件大小=" + length);
          }
          if (length <= 0) {
            return;
          }
          //创建文件保存路径
          File dir = new File(com.cmazxiaoma.downloader.download.DownLoadManager.FILE_PATH);
          if (!dir.exists()) {
            dir.mkdirs();//建立多级文件夹
          }
          newInfo.setLength(length);
          fileSize = length;
          UtilsLog.i("当前线程Id=" + java.lang.Thread.currentThread().getId() + ",name=" + java.lang.Thread.currentThread().getName());
          int currentPartSize = fileSize / mThreadNum;
          file = new File(com.cmazxiaoma.downloader.download.DownLoadManager.FILE_PATH, newInfo.getFileName());
          raf = new RandomAccessFile(file, "rwd");
          raf.setLength(fileSize);
          if (Thread.getInstance().isExist(newInfo.getUrl())) {
            flag = false;
          } else {
            flag = true;
          }
          for (int i = 0; i < mThreadNum; i++) {
            if (flag) {
              UtilsLog.i("第一次多线程下载");
              int start = i * currentPartSize;//计算每条线程下载的开始位置
              int end = start + currentPartSize-1;//线程结束的位置
              if(i==mThreadNum-1){
                end=fileSize;
              }
              String threadId = "xiaoma" + i;
              ThreadInfo threadInfo = new ThreadInfo(threadId, start, end, 0,newInfo.getUrl());
              Thread.getInstance().insert(threadInfo);
              DownLoadTask thread = new DownLoadTask(threadInfo,newInfo, threadId, start, end, 0);
              DownLoadManager.executorService.execute(thread);
              threads.add(thread);
            } else {
              UtilsLog.i("不是第一次多线程下载");
              ThreadInfo threadInfo = Thread.getInstance().query("xiaoma" + i, newInfo.getUrl());
              DownLoadTask thread = new DownLoadTask(threadInfo,newInfo,threadInfo.getThreadId(),threadInfo.getStart(),threadInfo.getEnd(),threadInfo.getCompeleted());//这里出现过问题
              DownLoadManager.executorService.execute(thread);
              threads.add(thread);
            }
          }
          boolean isCompleted=false;
          while(!isCompleted){
            isCompleted=true;
            for(DownLoadTask thread:threads){
              totalComleted+=thread.completed;
              if(!thread.isCompleted){
                isCompleted=false;
              }
            }
            if(newInfo.isStop()){
              totalComleted=0;
              return;
            }
            Message message=new Message();
            message.what=0x555;
            message.arg1=fileSize;
            message.arg2=totalComleted;
            handler.sendMessage(message);
            if(isCompleted){
              totalComleted=0;
              //任务线程全部完成,清空集合
              clear();
              handler.sendEmptyMessage(0x666);
              return;
            }
            totalComleted=0;
            java.lang.Thread.sleep(1000);
          }
        }catch (Exception e) {
          e.printStackTrace();
        }finally {
          try {
            if (con != null) {
              con.disconnect();
            }
            if(raf!=null){
              raf.close();
            }
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }.start();
  }
  private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
      super.handleMessage(msg);
      switch (msg.what){
        case 0x555:
          if(mlistener!=null){
            mlistener.progress(msg.arg1,msg.arg2);
          }
          break;
        case 0x666:
          if(mlistener!=null){
            mlistener.comleted();
          }
          break;
      }
    }
  };}

5.接下来呢,就是DownLoadTask类了,就是一个线程下载类。

 public class DownLoadTask extends java.lang.Thread{
  private int start;//当前线程的开始下载位置
  private int end;//当前线程结束下载的位置
  private RandomAccessFile raf;//当前线程负责下载的文件大小
  public int completed=0;//当前线程已下载的字节数
  private String threadId;//自己定义的线程Id
  private FileInfo info;
  private ThreadInfo threadInfo;
  public boolean isCompleted=false; //true为当前线程完成任务,false为当前线程未完成任务
  //保存新的start
  public int finshed=0;
  public int newStart=0;
  public DownLoadTask(ThreadInfo threadInfo,FileInfo info,String threadId, int start, int end,int completed){
    this.threadInfo=threadInfo;
    this.info=info;
    this.threadId=threadId;
    this.start=start;
    this.end=end;
    this.completed=completed;
  }
  @Override
  public void run() {
      HttpURLConnection con = null;
      try {
        UtilsLog.i("start="+start+",end="+end+",completed="+completed+",threadId="+getThreadId());
        URL url = new URL(info.getUrl());
        con = (HttpURLConnection) url.openConnection();
        con.setConnectTimeout(2 * 1000);
        con.setRequestMethod("GET");
        con.setRequestProperty("Range", "bytes=" + start + "-"+end);//重点
        raf=new RandomAccessFile(DownLoadManager.file,"rwd");
        //从文件的某一位置写入
        raf.seek(start);
        if (con.getResponseCode() == 206) { //文件部分下载 返回码是206
          InputStream is = con.getInputStream();
          byte[] buffer = new byte[4096];
          int hasRead = 0;
          while ((hasRead = is.read(buffer)) != -1) {
            //写入文件
            raf.write(buffer, 0, hasRead);
            //单个文件的完成程度
            completed += hasRead;
            threadInfo.setCompeleted(completed);
            //保存新的start
            finshed=finshed+hasRead;//这里出现过问题,嘻嘻
            newStart=start+finshed;
            threadInfo.setStart(newStart);
            //UtilsLog.i("Thread:"+getThreadId()+",completed="   + completed);
            //停止下载
            if (info.isStop()) {
              UtilsLog.i("isStop="+info.isStop());
              //保存下载进度
              UtilsLog.i("现在Thread:"+getThreadId()+",completed=" + completed);
              Thread.getInstance().update(threadInfo);
              return;
            }
          }
          //删除该线程下载记录
          Thread.getInstance().delete(threadInfo);
          isCompleted=true;
          Thread.getInstance().update(threadInfo);
          UtilsLog.i("thread:"+getThreadId()+"已经完成任务!--"+"completed="+completed);
        }
      } catch (Exception e) {
        if (con != null) {
          con.disconnect();
        }
        try {
          if (raf != null) {
            raf.close();
          }
        } catch (IOException e1) {
          e1.printStackTrace();
        }
      }
    }
  public String getThreadId() {
    return threadId;
  }}

6.接口,就是一个监听下载进度的接口,也是很简单。

 public interface ResultListener{
  void progress(int max, int progress);
  void comleted();}

结束

大致操作就是这样,其实多线程也挺简单的。

以上所述是小编给大家介绍的Android多线程+单线程+断点续传+进度条显示下载功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android的HTTP多线程下载示例代码

    本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 多线程断点需要的功能 1.多线程下载, 2.支持断点. 使用多线程的好处:使用多线程下载会提升文件下载的速度. 多线程下载文件的过程是: (1)首先获得下载文件的长度,然后设置本地文件的长度. HttpURLConnection.getContentLength();//获取下载文件的长度 RandomAccessFile file = new RandomAccessFile("QQWubiSetup.exe",&q

  • Android多线程断点续传下载功能实现代码

    原理 其实断点续传的原理很简单,从字面上理解,所谓断点续传就是从停止的地方重新下载. 断点:线程停止的位置. 续传:从停止的位置重新下载. 用代码解析就是: 断点:当前线程已经下载完成的数据长度. 续传:向服务器请求上次线程停止位置之后的数据. 原理知道了,功能实现起来也简单.每当线程停止时就把已下载的数据长度写入记录文件,当重新下载时,从记录文件读取已经下载了的长度.而这个长度就是所需要的断点. 续传的实现也简单,可以通过设置网络请求参数,请求服务器从指定的位置开始读取数据. 而要实现这两个功

  • android实现多线程下载文件(支持暂停、取消、断点续传)

    多线程下载文件(支持暂停.取消.断点续传) 多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将每一个线程下载的部分组装起来即可. 涉及的知识及问题 请求的数据如何分段 分段完成后如何下载和下载完成后如何组装到一起 暂停下载和继续下载的实现(wait().notifyAll().synchronized的使用) 取消下载和断点续传的实现 一.请求的数据如何分段 首先通过HttpURLConne

  • Android多线程学习实例详解

    本文实例分析了Android多线程.分享给大家供大家参考,具体如下: 在Android下面也有多线程的概念,在C/C++中,子线程可以是一个函数,一般都是一个带有循环的函数,来处理某些数据,优先线程只是一个复 杂的运算过程,所以可能不需要while循环,运算完成,函数结束,线程就销毁.对于那些需要控制的线程,一般我们都是和互斥锁相互关联,从而来控制线程 的进度,一般我们创建子线程,一种线程是很常见的,那就是带有消息循环的线程. 消息循环是一个很有用的线程方式,曾经自己用C在Linux下面实现一个

  • Android实现网络多线程断点续传下载实例

    我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多线程断点需要什么功能? 1.多线程下载, 2.支持断点. 使用多线程的好处:使用多线程下载会提升文件下载的速度.那么多线程下载文件的过程是: (1)首先获得下载文件的长度,然后设置本地文件的长度. HttpURLConnection.getContentLength();//获取下载文件的长度 RandomAccessFile file = new RandomAc

  • Android多线程之同步锁的使用

    本文主要介绍了Android多线程之同步锁的使用,分享给大家,具体如下: 一.同步机制关键字synchronized 对于Java来说,最常用的同步机制就是synchronized关键字,他是一种基于语言的粗略锁,能够作用于对象.函数.class.每个对象都只有一个锁,谁能够拿到这个锁谁就有访问权限.当synchronized作用于函数时,实际上锁的也是对象,锁定的对象就是该函数所在类的对象.而synchronized作用于class时则是锁的这个Class类,并非具体对象. public cl

  • Android 多线程实现重复启动与停止的服务

    Android 多线程实现重复启动与停止的服务 多线程环境下为了避免死锁,一般提倡开放调用,开放调用可以避免死锁,它的代价是失去原子性.但是在有些时候会显得逻辑错误, 例如: class A{ private boolean mIsStarted; void start(){ boolean changed = false; synchronized(this){ if(!mIsStarted){ mIsStarted = true; changed = false; } if(changed)

  • Android FTP 多线程断点续传下载\上传的实例

    最近在给我的开源下载框架Aria增加FTP断点续传下载和上传功能,在此过程中,爬了FTP的不少坑,终于将功能实现了,在此把一些核心功能点记录下载. FTP下载原理 FTP单线程断点续传 FTP和传统的HTTP协议有所不同,由于FTP没有所谓的头文件,因此我们不能像HTTP那样通过设置header向服务器指定下载区间. 但是FTP协议提供了一个更好用的命令REST用于从指定位置恢复任务,同时FTP协议也提供了一个命令SIZE用于获取下载的文件大小,有了这两个命令,FTP断点续传也就没有什么问题.

  • Android多线程+单线程+断点续传+进度条显示下载功能

    效果图 白话分析: 多线程:肯定是多个线程咯 断点:线程停止下载的位置 续传:线程从停止下载的位置上继续下载,直到完成任务为止. 核心分析: 断点: 当前线程已经下载的数据长度 续传: 向服务器请求上次线程停止下载位置的数据 con.setRequestProperty("Range", "bytes=" + start + "-" + end); 分配线程: int currentPartSize = fileSize / mThreadNum

  • Android自定义多节点进度条显示的实现代码(附源码)

    亲们里面的线段颜色和节点图标都是可以自定义的. 在没给大家分享实例代码之前,先给大家展示下效果图: main.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rl_parent" xmlns:tools="http://schemas.android.com/tools" android:layou

  • Android带进度条的下载图片示例(AsyncTask异步任务)

    为什么要用异步任务? 在Android中只有在主线程才能对ui进行更新操作,而其它线程不能直接对ui进行操作 android本身是一个多线程的操作系统,我们不能把所有的操作都放在主线程中操作 ,比如一些耗时操作.如果放在主线程中 会造成阻塞 而当阻塞事件过长时 系统会抛出anr异常.所以我们要使用异步任务.android为我们提供了一个封装好的组件asynctask. AsyncTask可以在子线程中更新ui,封装简化了异步操作.适用于简单的异步处理.如果多个后台任务时就要使用Handler了

  • Android 进度条显示在标题栏的实现方法

    好吧,先给大家展示效果图: xml文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content" > <Butt

  • 【CLI】利用Curl下载文件实时进度条显示的实现

    前言 最近在捣鼓命令行下的编程,下载文件总是一个难熬的过程,如果有进度条就好很多了!!! 先上一个进度条的扩展包,还是不错的https://github.com/dariuszp/cli-progress-bar (本地下载) 效果图: 还是挺好看的! curl有什么用? 用php ,curl主要是抓取数据,当然我们可以用其他的方法来抓取,比如fsockopen,file_get_contents等.但是只能抓那些能直接访问的页面,如果要抓取有页面访问控制的页面,或者是登录以后的页面就比较困难了

  • Python 给下载文件显示进度条和下载时间的实现

    大家在下载文件时能够显示下载进度和时间非常好,其实实现它方法很简单,这里我写了个进度条的模块,其中还附带上了运行时间也就是下载时间了. 该模块调用了三个库: 1.os 2.requests 3.time 话不多说,先上代码!!!. # 进度条模块 def progressbar(url,path): if not os.path.exists(path): # 看是否有该文件夹,没有则创建文件夹 os.mkdir(path) start = time.time() #下载开始时间 respons

  • Android实现支持进度条显示的短信备份工具类

    使用内容提供者读取短信内容,写入XML文件,进度条ProgressDialog更新备份进度. 新知识点:子线程如何在在不使用Handler的情况下更新UI /** * 进行短信备份的工具类,支持进度条显示 * @author lian * */ public class SmsBackupUtils { private static class Data{ int progress; } /** * * @param context * 调用此工具类的Activity * @param pd *

  • Android编程实现通知栏进度条效果的方法示例

    本文实例讲述了Android编程实现通知栏进度条效果的方法.分享给大家供大家参考,具体如下: /** * 通知管理工具类 * * @description: * @author ldm * @date 2016-5-3 上午9:39:56 */ public class NotificationUtil { private Context mContext; // NotificationManager : 是状态栏通知的管理类,负责发通知.清楚通知等. private Notification

  • Android实现个性化的进度条

    1.案例效果图 2.准备素材 progress1.png(78*78) progress2.png(78*78) 3.原理 采用一张图片作为ProgressBar的背景图片(一般采用颜色比较浅的).另一张是进度条的图片(一般采用颜色比较深的图片).进度在滚动时:进度图片逐步显示,背景图片逐步隐藏,达到上面的效果. 4.灵感来自Android控件提供的源码 4.1 默认带进度的进度条,如下图 <ProgressBar android:id="@+id/progressBar2" s

  • android ListView和ProgressBar(进度条控件)的使用方法

    ListView控件的使用:ListView控件里面装的是一行一行的数据,一行中可能有多列,选中一行,则该行的几列都被选中,同时可以触发一个事件,这种控件在平时还是用得很多的.使用ListView时主要是要设置一个适配器,适配器主要是用来放置一些数据.使用起来稍微有些复杂,这里用的是android自带的SimpleAdapter,形式如下:android.widget.SimpleAdapter.SimpleAdapter(Context context, List<? extends Map<

随机推荐