第8讲多线程

第8讲多线程

案例:

用AsyncTask来实现文件下载,要求:

a)  可在文本框中输入请求路径,点击按钮开始下载

b)  在界面上实时更新下载进度

c)  如果文件已存在,则删除原文件再进行下载

 

涉及知识点及步骤

1.创建布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/url"
android:text="http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="下载"
        android:id="@+id/download_button"/>

    <ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:id="@+id/progressBar"/>

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"/>
</LinearLayout>

2.Java

涉及知识点:

 

 

AsyncTask介绍

Android的AsyncTask比Handler更轻量级一些,适用于简单的异步处理。

首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。

 Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务类,顾名思义就是异步任务。

AsyncTask直接继承于Object类,位置为android.os.AsyncTask。要使用AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。

AsyncTask定义了三种泛型类型Params,Progress和Result。

Params 启动任务执行的输入参数,比如HTTP请求的URL。

Progress 后台任务执行的百分比。

Result 后台执行任务最终返回的结果,比如String。

使用AsyncTask最少要重写以下这两个方法:

doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。

onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

有必要的话你还得重写以下这三个方法,但不是必须的:

onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。

onPreExecute()        这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。

onCancelled()             用户调用取消时,要做的操作

使用AsyncTask类,以下是几条必须遵守的准则:

Task的实例必须在UI thread中创建;

execute方法必须在UI thread中调用;

不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)这几个方法;

该task只能被执行一次,否则多次调用时将会出现异常;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    public static final String FXC = "fxc";
    private TextView mTextView;
    private Button mDownloadButton;
    private ProgressBar mProgressBar;
    private EditText mEditText;
    private static  String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";
    public static final String TAG = MainActivity.class.getSimpleName();

    private Handler mHandler = new DownloadHandler(this);

    public TextView getTextView() {
        return mTextView;
    }

    public ProgressBar getProgressBar() {
        return mProgressBar;
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate ( savedInstanceState );
        setContentView ( R.layout.activity_main );

        mTextView = (TextView) findViewById(R.id.text_view);

        mDownloadButton = (Button) findViewById(R.id.download_button);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mEditText = (EditText) findViewById(R.id.url);
       APK_URL=mEditText.getText ().toString ().trim ();

        mDownloadButton.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.download_button:
                 new TestTask().execute(2,3,4);
                break;
        }
    }

    class TestTask extends AsyncTask<Integer,Integer,String> {

        @Override
        protected void onPreExecute() {
                super.onPreExecute();
        }

        @Override
        protected String doInBackground(Integer... params) {
                        download(APK_URL);
            return String.valueOf(params[0] * 2 + 2);
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
          }
    }


    private void download(String apkUrl) {
        try {
            URL url = new URL(apkUrl);
            URLConnection urlConnection = url.openConnection();

            InputStream inputStream = urlConnection.getInputStream();

            int contentLength = urlConnection.getContentLength();

            String downloadFoldersName = Environment.getExternalStorageDirectory() + File.separator ;
            File file = new File(downloadFoldersName);
            if (!file.exists()) {
                file.mkdir();
            }

            String fileName = downloadFoldersName + "test.apk";
            File apkFile = new File(fileName);
            if (apkFile.exists()) {
                apkFile.delete();
            }

            int downloadSize = 0;

            byte[] bytes = new byte[1024];
            int length = 0;

            OutputStream outputStream = new FileOutputStream (fileName);

            while ((length = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, length);
                downloadSize += length;
                int progress = downloadSize * 100 / contentLength;
                // update UI

                Message message = mHandler.obtainMessage();
                message.obj = progress;
                message.what = 0;
                mHandler.sendMessage(message);

                Log.i(TAG, "download progress: " + progress);
            }
            Log.i(TAG, "download success");
            inputStream.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
            Log.i(TAG, "download failure");
        }
    }

    public static class DownloadHandler extends Handler {

        public final WeakReference<MainActivity> mActivity;

        public DownloadHandler(MainActivity activity) {
            mActivity = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MainActivity activity = mActivity.get();

            switch (msg.what) {
                case 0:
                    int progress = (int) msg.obj;
                    activity.getProgressBar().setProgress(progress);
                    activity.getTextView().setText("progress:" + progress);
                    if(progress == 100){
                        Toast.makeText(activity, "download success", Toast.LENGTH_SHORT).show();
                    }
                    break;
            }
        }
    }

}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值