AsyncTask的學習

一週沒學習,累覺不愛,週一新刀到手,結果就把手指給切了5MM深1cm寬,直接縫了四針,真是痛苦到極點了!隔一天還得換次藥,現在總算不是太影響敲代碼了,感覺有點爲自己開脫的感覺。花了300多,一週時間,真的很不划算,開始敲代碼吧。。


AsyncTask的學習

AsyncTask就是對Handler和Thread的封裝,簡化了一些操作

常見的方法有四個:
onPreExecute(); 執行在主線程中,異步任務前開始前調用.
doInBackground();執行在子線程中,異步任務的過程中調用.
onPostExecute();執行在主線程中,任務完成後調用.
onProgressUpdate();執行在主線程中,在執行過程中操作進度的改變.


/**
 *   異步下載demo
 *   1:準備權限相關:  網絡權限  讀寫存儲設備權限
 *   2: 界面 Layoout
 *   3:下載前要做的事情
 *   4:下載中要做的事情
 *   5:下載完成後要做的事情
 */

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private static final int INIT_PROGRESS = 0;
    private static final String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";
    private static final String APK_NAME = "aaaa.apk";
    private ProgressBar mProgressBar;
    private Button mButton;
    private TextView mDwonLoadText;

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

    private void initView() {
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mButton = (Button)findViewById(R.id.button);
        mDwonLoadText = (TextView)findViewById(R.id.tv_download);
    }

    private void initData() {
        mProgressBar.setProgress(INIT_PROGRESS);//設置進度
        mButton.setText(R.string.click_dwonload);
        mDwonLoadText.setText(R.string.click_dwonload);
    }

    private void initListener() {
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //點擊開始下載....執行耗時操作
                DwonloadAsyncTask dwonloadAsyncTask = new DwonloadAsyncTask();
                //傳入的參數。。 可以是任何參數  這裏一般傳入url地址
                dwonloadAsyncTask.execute(APK_URL);
            }
        });
    }

    /**
     *  String 參入的參數
     *  Integer 進度條的進度
     *  Boolean  返回值
     */
    class DwonloadAsyncTask extends AsyncTask<String,Integer,Boolean>{

        //獲取文件存儲的路徑
        String apkPash = Environment.getExternalStorageDirectory()+File.separator+ APK_NAME +File.separator;

        /**
         * 此方法執行在子線程中,是AsnycTask執行的開始方法,在異步任務之前執行
         * 一般用來操作ui
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        /**
         * 此方法執行在子線程中,是AsnycTask的執行過程中的方法
         * @param params 入參
         * @return  出參
         */
        @Override
        protected Boolean doInBackground(String... params) {
            if (params!=null && params.length>0){
                //接受params傳入進來的參數
                String apkUrl = params[0];
                try {
                    //創建URL
                    URL url = new URL(apkUrl);
                    //創建連接 並打開
                    URLConnection conn = url.openConnection();
                    //獲取url的一些參數
                    //連接文件的總大小
                    int contentLength = conn.getContentLength();
                    //獲取文件的輸入流
                    InputStream is = conn.getInputStream();
                    //獲取文件存儲的路徑
                    String apkPash = Environment.getExternalStorageDirectory()+File.separator+ APK_NAME +File.separator;
                    File file = new File(apkPash);
                    //對文件路徑做下處理
                    if(file.exists()){
                        //如果不爲空刪除文件
                        file.delete();
                    }

                    //記錄已經下載的大小
                    int downLoadSize =0;
                    //記錄每次下載大小
                    int len = 0;
                    //每次下載多少字節
                    byte[] bytes = new byte[1024];
                    //創建文件輸出流管道
                    OutputStream os = new FileOutputStream(apkPash);
                    //開始下載文件
                    while ((len = is.read(bytes)) != -1){
                        //記錄每次下載的進度
                        downLoadSize += len;
                        os.write(bytes,0,len);
                        //處理進度條 拋出進度
                        publishProgress(downLoadSize*100 /contentLength);
                    }
                    os.close();
                    is.close();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return true;
            }else{
                return  false;
            }
        }

        /**
         * 此方法執行在主線程中,在異步任務執行完後
         * 一般用來操作結果
         * @param b
         */
        @Override
        protected void onPostExecute(Boolean b) {
            //更新UI
            mButton.setText(b?"下載完成":"下載失敗");
            mDwonLoadText.setText(b?"下載完成"+apkPash:"下載失敗");
        }

        /**
         * 在執行過程中操作進度的改變
         * @param values
         */
        @Override
        protected void onProgressUpdate(Integer... values) {
            if(values !=null && values.length>0){
                //接受進度
                Integer value = values[0];
                //更新進度條
                mProgressBar.setProgress(value);
            }
        }
    }


}

簡單封裝下步驟


public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";
    private static final int INIT_PROGRESS = 0;
    private static final String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";
    private static final String APK_NAME = "aaaa.apk";
    private ProgressBar mProgressBar;
    private Button mButton;
    private TextView mDwonLoadText;

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

    }

    private void initView() {
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mButton = (Button)findViewById(R.id.button);
        mDwonLoadText = (TextView)findViewById(R.id.tv_download);
    }

    private void initData() {
        mProgressBar.setProgress(INIT_PROGRESS);//設置進度
        mButton.setText(R.string.click_dwonload);
        mDwonLoadText.setText(R.string.click_dwonload);
    }

    private void initListener() {
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //獲取文件存儲的路徑
                final String apkPath = Environment.getExternalStorageDirectory()+File.separator+ APK_NAME +File.separator;
                mButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        DwonLoadHelper.dwonLoad(APK_URL, apkPath, new DwonLoadHelper.OnDownLoadListener() {
                            @Override
                            public void onStart() {
                                mButton.setText("正在下載");
                                mDwonLoadText.setText("正在下載");
                            }

                            @Override
                            public void onSuccess(int code, File file) {
                                mButton.setText("下載完成");
                                mDwonLoadText.setText("下載完成"+apkPath);
                            }

                            @Override
                            public void onFail(int code, File file, String message) {
                                Log.i(TAG,message);
                            }
                            @Override
                            public void onProgress(int progress) {
                                mProgressBar.setProgress(progress);
                            }
                        });
                    }
                });
            }
        });
    }



}
----------


----------


/**
 *  對AsyncTask異步下載的簡單封裝
 *  定義下載方法,傳入必要的url path  listener參數  在AsyncTask裏進行回調
 *  定義接口
 */
public class DwonLoadHelper {

    public static void dwonLoad(String url ,String FilePath,OnDownLoadListener listener){
        DwonloadAsyncTask dwonloadAsyncTask = new DwonloadAsyncTask(url,FilePath,listener);
        dwonloadAsyncTask.execute();
    }

    static class DwonloadAsyncTask extends AsyncTask<String,Integer,Boolean> {
        public String mUrl;
        public String mFilePath;
        public OnDownLoadListener mListener;

        public DwonloadAsyncTask(String mUrl, String mFilePath, OnDownLoadListener mListener) {
            this.mUrl = mUrl;
            this.mFilePath = mFilePath;
            this.mListener = mListener;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if(mListener !=null){
                mListener.onStart();
            }
        }
        @Override
        protected Boolean doInBackground(String... params) {
                if(mListener!=null){
                    try {
                        //創建URL
                        URL url = new URL(mUrl);
                        //創建連接 並打開
                        URLConnection conn = url.openConnection();
                        //連接文件的總大小
                        int contentLength = conn.getContentLength();
                        //獲取文件的輸入流
                        InputStream is = conn.getInputStream();
                        File file = new File(mFilePath);
                        //對文件路徑做下處理
                        if(file.exists()){
                            //如果不爲空刪除文件
                            file.delete();
                        }
                        //記錄已經下載的大小
                        int downLoadSize =0;
                        //記錄每次下載大小
                        int len = 0;
                        //每次下載多少字節
                        byte[] bytes = new byte[1024];
                        //創建文件輸出流管道
                        OutputStream os = new FileOutputStream(mFilePath);
                        //開始下載文件
                        while ((len = is.read(bytes)) != -1){
                            //記錄每次下載的進度
                            downLoadSize += len;
                            os.write(bytes,0,len);
                            //處理進度條 拋出進度
                            publishProgress(downLoadSize*100 /contentLength);
                        }
                        os.close();
                        is.close();
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return true;
                }else{
                    mListener.onFail(-2,new File(mFilePath),"文件下載失敗");
                    return  false;
                }
        }

        /**
         * 此方法執行在主線程中,在異步任務執行完後
         * 一般用來操作結果
         * @param b
         */
        @Override
        protected void onPostExecute(Boolean b) {
            //更新UI
            if(mListener !=null){
                mListener.onSuccess(1,new File(mFilePath));
            }else{
             mListener.onFail(-1,new File(mFilePath),"文件下載失敗");
            }
        }

        /**
         * 在執行過程中操作進度的改變
         * @param values
         */
        @Override
        protected void onProgressUpdate(Integer... values) {
            if(values !=null && values.length>0){
                //接受進度
                Integer value = values[0];
                if(mListener!=null){
                    mListener.onProgress(value);
                }
            }
        }
    }

    /**
     * 定義接口,定義必要的一些方法回調
     */
    public interface OnDownLoadListener {
        void onStart();
        void onSuccess (int code ,File file);
        void onFail(int code, File file, String message);
        void onProgress(int progress);
        //對接口簡單的小優化。有時候不需要用到那麼多方法,只定義幾個必須要用到的就可以了
        //只用成功失敗的方法話,在接口調用時,用此類即可
        abstract class SimpleDwonLoad implements OnDownLoadListener{
            @Override
            public void onSuccess(int code, File file) {
            }
            @Override
            public void onFail(int code, File file, String message) {
            }
        }
    }

}

對接口的回調和寫法有了一點了解,
可以把一些邏輯代碼封裝調用接口裏的方法處理結果,讓回調者在外面處理業務邏輯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章