Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android異步任務 訪問網絡 加載圖片 解決方案大集合

android異步任務 訪問網絡 加載圖片 解決方案大集合

編輯:關於Android編程

1. Handler + Thread 異步執行任務

在UI線程中開啟子線程,使用Handler 發消息,通知主線程更新UI
直接在UI線程中開啟子線程來更新TextView顯示的內容,運行程序我們會發現,如下錯誤:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.翻譯過來就是:只有創建這個控件的線程才能去更新該控件的內容。
所有的UI線程要去負責View的創建並且維護它,例如更新冒個TextView的顯示,都必須在主線程中去做,我們不能直接在UI線程中去創建子線程,要利用消息機制:handler,如下就是handler的簡單工作原理圖:
\
public class HandlerTestActivity extends Activity {
    private TextView tv;
    private static final int UPDATE = 0;
    private Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // TODO 接收消息並且去更新UI線程上的控件內容
            if (msg.what == UPDATE) {
                // Bundle b = msg.getData();
                // tv.setText(b.getString("num"));
                tv.setText(String.valueOf(msg.obj));
            }
            super.handleMessage(msg);
        }
    };

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv = (TextView) findViewById(R.id.tv);

        new Thread() {
            @Override
            public void run() {
                // TODO 子線程中通過handler發送消息給handler接收,由handler去更新TextView的值
                try {
                    for (int i = 0; i < 100; i++) {
                        Thread.sleep(500);
                        Message msg = new Message();
                        msg.what = UPDATE;
                        // Bundle b = new Bundle();
                        // b.putString("num", "更新後的值:" + i);
                        // msg.setData(b);
                        msg.obj = "更新後的值:" + i;
                        handler.sendMessage(msg);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

}
-------------請求網絡數據-----------------------------------
 new Thread() {
                    @Override
                    public void run() {
                        // 使用 okHttp 請求網絡       
                        OkHttpClient okHttpClient = new OkHttpClient();
                        Request request = new Request.Builder().url(SERVERURL).build();
                        try {
                            Response response = okHttpClient.newCall(request).execute();
                            String result = response.body().string();
                            Message msg = new Message();
                            msg.what = 0;
                            Bundle bundle = new Bundle();
                            bundle.putString("result", result);
                            msg.setData(bundle);
                            handler.sendMessage(msg);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }.start();

2. AsyncTask抽象類 (一個異步任務框架)

更輕量級一些,適用於簡單的異步處理,不需要借助線程和Handler即可。

android提供了一套專門用於異步處理的類。即:AynsTask類。使用這個類可以為耗時程序開辟一個新線程進行處理,處理完時返回。
其實,AsynTask類就是對Thread類的一個封裝,並且加入了一些新的方法。編程時,兩者都可以實現同樣的功能。本文後面將對AsynTask和Thread進行比較

AsyncTask抽象類

AsyncTask

//在主線程調用該方法
    private void useAsyncTask() {
        /*主線程調用AsynTask子類實例的execute()方法後,首先會調用onPreExecute()方法。
        onPreExecute()在主線程中運行,可以用來寫一些開始提示代碼。*/
        DownLoader downLoader = new DownLoader(textView);
/*execute()向doInBackground()傳遞。*/
        downLoader.execute(SERVERURL);

    }
                //Params:啟動任務執行的輸入參數的類型。 

                //Progress:後台任務完成進度值的類型。 

                //Result:後台執行任務完成後返回結果的類型
    class DownLoader extends AsyncTask {
        TextView text;

        public DownLoader(TextView text) {
            this.text = text;
        }

        /*處理完畢之後異步線程結束,在主線程中調用onPostExecute()方法。onPostExecute()可以進行一些結束提示處理*/
        @Override
        protected String doInBackground(String... params) {

            String url = params[0];
            String result = null;
            OkHttpClient okHttpClient = new OkHttpClient();
            Request request = new Request.Builder().url(url).build();
            Response response = null;
            try {
                response = okHttpClient.newCall(request).execute();
                result = response.body().string();
            } catch (IOException e) {
                e.printStackTrace();
            }
            /*//publishProgress()為AsyncTask類中的方法
            //常在doInBackground()中調用此方法
            //用於通知主線程,後台任務的執行情況.
            //此時會觸發AsyncTask中的onProgressUpdate()方法*/

/* doInBackground()的返回值會傳遞給onPostExecute()。*/
            return result;
        }

        @Override
        protected void onCancelled(String s) {
            super.onCancelled(s);
        }

        /*onProgressUpdate()方法用於更新異步執行中,在主線程中處理異步任務的執行信息  參數為publishProgress() 方法的參數*/
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        /*處理完畢之後異步線程結束,在主線程中調用onPostExecute()方法。onPostExecute()可以進行一些結束提示處理*/
        @Override
        protected void onPostExecute(String s) {
//            super.onPostExecute(s);

            text.setText(s);

        }

        /*之後啟動新線程,調用doInBackground()方法,進行異步數據處理。*/
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            System.out.println("開始執行異步任務.....");
        }

        /*onCancelled()方法用於異步任務被取消時,在主線程中執行相關的操作*/
        @Override
        protected void onCancelled() {
            super.onCancelled();
        }
    }

參考鏈接 ; http://blog.csdn.net/guolin_blog/article/details/9526203

網絡加載框架

Volley

Volley 是 Google 推出的 Android 異步網絡請求框架和圖片加載框

參考鏈接: http://blog.csdn.net/guolin_blog/article/details/17482095/
* 它的設計目標就是非常適合去進行數據量不大,但通信頻繁的網絡操作,而對於大數據量的網絡操作,比如說下載文件等,Volley的表現就會非常糟糕。

volley 在android studio中如何使用

這裡寫圖片描述

StringRequest的用法
 private void uesVolley() {
    /*1. 創建一個RequestQueue對象。
    2. 創建一個StringRequest對象。
    3. 將StringRequest對象添加到RequestQueue裡面。
    */
        /**
         * 注意這裡拿到的RequestQueue是一個請求隊列對象,它可以緩存所有的HTTP請求,
         * 然後按照一定的算法並發地發出這些請求。RequestQueue內部的設計就是非常合適高並發的,
         * 因此我們不必為每一次HTTP請求都創建一個RequestQueue對象,這是非常浪費資源的,
         * 基本上在每一個需要和網絡交互的Activity中創建一個RequestQueue對象就足夠了。
         */
        RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);

/**
 * 這裡new出了一個StringRequest對象,StringRequest的構造函數需要傳入三個參數,
 * 第一個參數就是目標服務器的URL地址
 * 第二個參數是服務器響應成功的回調,
 * 第三個參數是服務器響應失敗的回調
 */
        StringRequest stringRequest = new StringRequest("http://www.baidu.com", new com.android.volley.Response.Listener() {
            @Override
            public void onResponse(String response) {
                textView.setText(response);
                Log.d("TAG", response);

            }
        }, new com.android.volley.Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
      //最後,將這個StringRequest對象添加到RequestQueue裡面就可以了
        mQueue.add(stringRequest);
/**
 * TTP的請求類型通常有兩種,GET和POST,剛才我們使用的明顯是一個GET請求,那麼如果想要發出一條POST請求應該怎麼做呢?
 * StringRequest中還提供了另外一種四個參數的構造函數,其中第一個參數就是指定請求類型的
 */
        StringRequest stringRequestPost = new StringRequest(com.android.volley.Request.Method.POST, SERVERURL,
                successListener, errorLiatener) {
            @Override
            protected Map getParams() throws AuthFailureError {

                HashMap map = new HashMap<>();
                map.put("useName", "admin");
                map.put("password", "123456");

                return map;
            }
        };
        mQueue.add(stringRequestPost);


    }
JsonRequest的用法
學完了最基本的StringRequest的用法,我們再來進階學習一下JsonRequest的用法。類似於StringRequest,JsonRequest也是繼承自Request類的,不過由於JsonRequest是一個抽象類,因此我們無法直接創建它的實例,那麼只能從它的子類入手了。JsonRequest有兩個直接的子類,JsonObjectRequest和JsonArrayRequest,從名字上你應該能就看出它們的區別了吧?一個是用於請求一段JSON數據的,一個是用於請求一段JSON數組的。
至於它們的用法也基本上沒有什麼特殊之處,先new出一個JsonObjectRequest對象
  /*  JsonRequest的用法*/
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(SERVERURL, null,
                new com.android.volley.Response.Listener() {
            @Override
            public void onResponse(JSONObject response) {
                textView.setText(response.toString());
                Log.e("JsonObject",response.toString());

            }
        }, new com.android.volley.Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        });
        mQueue.add(jsonObjectRequest);
ImageRequest的用法

參考鏈接: http://blog.csdn.net/guolin_blog/article/details/17482165

 private void loadImage() {

        RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);
       ImageRequest imageRequest =  new ImageRequest("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/logo_white_fe6da1ec.png",
                new com.android.volley.Response.Listener() {
                    @Override
                    public void onResponse(Bitmap response) {
                        image.setImageBitmap(response);
                    }
                },
                0, 0, Bitmap.Config.RGB_565,
                new com.android.volley.Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                }

        );
        mQueue.add(imageRequest);


    }

可以看到,ImageRequest的構造函數接收六個參數,第一個參數就是圖片的URL地址,這個沒什麼需要解釋的。第二個參數是圖片請求成功的回調,這裡我們把返回的Bitmap參數設置到ImageView中。第三第四個參數分別用於指定允許圖片最大的寬度和高度,如果指定的網絡圖片的寬度或高度大於這裡的最大值,則會對圖片進行壓縮,指定成0的話就表示不管圖片有多大,都不會進行壓縮。第五個參數用於指定圖片的顏色屬性,Bitmap.Config下的幾個常量都可以在這裡使用,其中ARGB_8888可以展示最好的顏色屬性,每個圖片像素占據4個字節的大小,而RGB_565則表示每個圖片像素占據2個字節大小。第六個參數是圖片請求失敗的回調,這裡我們當請求失敗時在ImageView中顯示一張默認圖片。
最後將這個ImageRequest對象添加到RequestQueue裡就可以了

ImageLoader的用法

ImageLoader也可以用於加載網絡上的圖片,並且它的內部也是使用ImageRequest來實現的,不過ImageLoader明顯要比ImageRequest更加高效,因為它不僅可以幫我們對圖片進行緩存,還可以過濾掉重復的鏈接,避免重復發送請求。
由於ImageLoader已經不是繼承自Request的了,所以它的用法也和我們之前學到的內容有所不同,總結起來大致可以分為以下四步:

創建一個RequestQueue對象。

創建一個ImageLoader對象。

獲取一個ImageListener對象。

調用ImageLoader的get()方法加載網絡上的圖片。

  private void loadImage() {


/*,ImageLoader的構造函數接收兩個參數,第一個參數就是RequestQueue對象,第二個參數是一個ImageCache對象*/
        ImageLoader imageLoader = new ImageLoader(mQueue, new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                return null;
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {

            }
        });
        /*我們通過調用ImageLoader的getImageListener()方法能夠獲取到一個ImageListener對象,
        getImageListener()方法接收三個參數,
        第一個參數指定用於顯示圖片的ImageView控件,
        第二個參數指定加載圖片的過程中顯示的圖片,
        第三個參數指定加載圖片失敗的情況下顯示的圖片*/
        ImageLoader.ImageListener imageListener = ImageLoader.getImageListener(image,
                R.mipmap.ic_launcher,
                R.mipmap.ic_download);
/*get()方法接收兩個參數,第一個參數就是圖片的URL地址,第二個參數則是剛剛獲取到的ImageListener對象。
當然,如果你想對圖片的大小進行限制,也可以使用get()方法的重載,指定圖片允許的最大寬度和高度*/
        imageLoader.get(imageUrl,imageListener,200,200);
    }
NetworkImageView

除了以上兩種方式之外,Volley還提供了第三種方式來加載網絡圖片,即使用NetworkImageView。不同於以上兩種方式,NetworkImageView是一個自定義控制,它是繼承自ImageView的,具備ImageView控件的所有功能,並且在原生的基礎之上加入了加載網絡圖片的功能。NetworkImageView控件的用法要比前兩種方式更加簡單,大致可以分為以下五步:
1. 創建一個RequestQueue對象。
2. 創建一個ImageLoader對象。
3. 在布局文件中添加一個NetworkImageView控件。
4. 在代碼中獲取該控件的實例。
5. 設置要加載的圖片地址。

xml文件

 

java代碼

private void useNetworkImageView() {

        RequestQueue mQueue = Volley.newRequestQueue(MainActivity.this);
        /*,ImageLoader的構造函數接收兩個參數,第一個參數就是RequestQueue對象,第二個參數是一個ImageCache對象*/
        ImageLoader imageLoader = new ImageLoader(mQueue, new ImageLoader.ImageCache() {
            @Override
            public Bitmap getBitmap(String url) {
                return null;
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {

            }
        });
        ivNetWorkImage.setDefaultImageResId(R.mipmap.ic_download);
        ivNetWorkImage.setErrorImageResId(R.mipmap.ic_launcher);
        ivNetWorkImage.setImageUrl(imageUrl, imageLoader);

    }

LruCache

android Studio 使用 butterknife 注解功能

需要添加下面一行依賴
       compile 'com.jakewharton:butterknife:7.0.1'

Picasso 圖片緩存框架

使用:
依賴中搜索 Picasso ,點擊添加

picasso是Square公司開源的一個Android圖形緩存庫,地址http://square.github.io/picasso/,

可以實現圖片下載和緩存功能。僅僅只需要一行代碼就能完全實現圖片的異步加載

參考鏈接: http://bbs.itcast.cn/thread-87019-1-1.html

參考鏈接: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0731/1639.html

簡單用例—從網絡加載:
  /**
         * 圖片下載的步驟:
         * 1、使用異步任務或者 handler+thread 獲取圖片資源
         * 2、使用bitmapFactory 對圖片進行解碼
         * 3、顯示圖片
         */
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Picasso
                        .with(MainActivity.this)
                        .load(imageUrl)//有多個重載方法
                        .placeholder(R.mipmap.ic_launcher)//,默認顯示圖片
                        .error(R.mipmap.ic_launcher)//加載錯誤時顯示的圖片
                        .resize(80,80)//轉換圖片以適應布局大小並減少內存占用
                        .centerCrop()
//                        .transform(new CustomeCropAquareTransFormation()) //自定義轉換
                        .into(imageView);//顯示到指定控件上
            }
        });

//自定義裁剪,將 CustomeCropSquareTransformation 的對象傳遞給transform 方法即可

 public class CustomeCropAquareTransFormation implements Transformation{

        @Override
        public Bitmap transform(Bitmap bitmap) {
            int size = Math.min(bitmap.getWidth(),bitmap.getHeight());//得到 Width 和 Height 的最小值
          //判斷以高度進行縮減還是以高度進行縮減
            int x= (bitmap.getWidth()-size)/2;
            int y = (bitmap.getHeight()-size)/2;
            Bitmap resultBitmap = Bitmap.createBitmap(bitmap, x, y, 80, 80);//從原始位圖剪切圖像
            if(resultBitmap!=bitmap){
                bitmap.recycle();//回收Bitmap資源
            }
            return resultBitmap;
        }

        @Override
        public String key() {
            return "square";
        }
    }

load() 有多個重載方法 也可以從 從Android Resources 中加載 , 從本地File文件中加載 , 從URI地址中加載

Picasso不僅實現了圖片異步加載的功能,還解決了android中加載圖片時需要解決的一些常見問題:

   1.在adapter中需要取消已經不在視野范圍的ImageView圖片資源的加載,否則會導致圖片錯位,Picasso已經解決了這個問題。

   2.使用復雜的圖片壓縮轉換來盡可能的減少內存消耗

   3.自帶內存和硬盤二級緩存功能

public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)

從原始位圖剪切圖像,這是一種高級的方式。可以用Matrix(矩陣)來實現旋轉等高級方式截圖
參數說明:

          Bitmap source:要從中截圖的原始位圖

          int x:起始x坐標

          int y:起始y坐標

            int width:要截的圖的寬度

            int height:要截的圖的寬

           返回值:返回一個剪切好的Bitmap

Universal ImageLoader

github: https://github.com/nostra13/Android-Universal-Image-Loader

參考鏈接1: http://blog.csdn.net/vipzjyno1/article/details/23206387

參考鏈接2: http://blog.csdn.net/wwj_748/article/details/10079311/

參考鏈接:Android-Universal-Image-Loader三大組件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration詳解

UIL是是一個開源項目,其目的就是提供一個可重復使用的儀器為異步圖像加載、緩存和顯示。它的使用很簡單:

盡管Picasso擁有更好的API,但其缺乏自定義。而使用UIL構建器幾乎可以配置所有(其中最重要的就是在抓取和緩存大型圖片時,Picasso會失敗)。

簡單描述一下這個項目的結構:每一個圖片的加載和顯示任務都運行在獨立的線程中,除非這個圖片緩存在內存中,這種情況下圖片會立即顯示。如果需要的圖片緩存在本地,他們會開啟一個獨立的線程隊列。如果在緩存中沒有正確的圖片,任務線程會從線程池中獲取,因此,快速顯示緩存圖片時不會有明顯的障礙。(別人那邊借鑒的這段)

流程圖:

這裡寫圖片描述vc/uxL/A78PmLDwvY29kZT48L2NvZGU+PC9jb2RlPjwvcD4NCjxwPjxjb2RlPjxjb2RlPjxjb2RlPm1haW5mINbQzO2808ioz948L2NvZGU+PC9jb2RlPjwvY29kZT48L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;"> 重點有三個重要的類:

ImageLoaderConfiguration: 是針對圖片緩存的全局配置,主要有線程類、緩存大小、磁盤大小、圖片下載與解析、日志方面的配置。

/**
 * 全局配置 ImageLoaderConfiguration
 * 先要配置ImageLoaderConfiguration這個類實現全局ImageLoader的實現情況。
 */
public class MyApplecation extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ImageLoaderConfiguration config;
        config = new ImageLoaderConfiguration
                .Builder(MyApplecation.this)
                .memoryCacheExtraOptions(480,800)// max width, max height,即保存的每個緩存文件的最大長寬
//                .diskCacheExtraOptions()
                .threadPoolSize(3)//線程池內加載的數量
                .threadPriority(Thread.NORM_PRIORITY-2)
                .denyCacheImageMultipleSizesInMemory()
//                .memoryCache(new UsingFreqLimitedMemoryCache(2*1024*1024))//你可以通過自己的內存緩存實現
                .memoryCacheSize(2*1024*1024)//內存緩存大小
                .diskCacheSize(50*1024*1024)//磁盤緩存大小
//                .diskCacheFileNameGenerator(new Md5FileNameGenerator())//將保存的時候的URI名稱用MD5 加密
                .tasksProcessingOrder(QueueProcessingType.FIFO)//設置線程池隊列任務,為FIFO(先進先出)
                .diskCacheFileCount(100)//設置磁盤緩存的文件最大數量
//                .diskCache(new UnlimitedDiskCache(cacheDir))// 自定義緩存路徑
                .defaultDisplayImageOptions(DisplayImageOptions.createSimple())//顯示的圖片的各種格式DisplayImageOptions 的設置
                .imageDownloader(new BaseImageDownloader(MyApplecation.this,5*1000,30*1000))
                .writeDebugLogs()// Remove for release app
                .build();//構建完成

        //配置好ImageLoaderConfiguration後,調用以下方法來實現初始化:
        ImageLoader.getInstance().init(config);
        class BaseImageDowner implements ImageDownloader {

            @Override
            public InputStream getStream(String imageUri, Object extra) throws IOException {
                return null;
            }
        }
    }
}

DisplayImageOptions 用於指導每一個Imageloader根據網絡圖片的狀態(空白、下載錯誤、正在下載)顯示對應的圖片,是否將緩存加載到磁盤上,下載完後對圖片進行怎麼樣的處理

DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher)//設置圖片在下載期間顯示的圖片
                .showImageForEmptyUri(R.drawable.weixin)//設置圖片Uri為空或是錯誤的時候顯示的圖片
                .showImageOnFail(R.drawable.feng3)//設置圖片加載/解碼過程中錯誤時候顯示的圖片
                .cacheInMemory(true)//設置下載的圖片是否緩存在內存中
                .cacheOnDisk(true)//設置下載的圖片是否緩存在SD卡中
                .considerExifParams(true)  //是否考慮JPEG圖像EXIF參數(旋轉,翻轉)
                .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) //設置圖片以如何的編碼方式顯示
                .bitmapConfig(Bitmap.Config.RGB_565)//設置圖片的解碼類型
//                .delayBeforeLoading(1000)//int delayInMillis為你設置的下載前的延遲時間

                //.preProcessor(BitmapProcessor preProcessor)  //設置圖片加入緩存前,對bitmap進行設置
                .resetViewBeforeLoading(true)// 設置圖片在下載前是否重置,復位
                .displayer(new RoundedBitmapDisplayer(20))//是否設置為圓角,弧度為多少
                .displayer(new FadeInBitmapDisplayer(100))//是否圖片加載好後漸入的動畫時間
                .build();

ImageLoader :是具體下載圖片,緩存圖片,顯示圖片的具體執行類,它有兩個具體的方法displayImage(…)、loadImage(…),但是其實最終他們的實現都是displayImage(…)

displayImage(…) 方法有多個重載

1.使用默認配置

 // imageUrl代表圖片的URL地址,imageView代表承載圖片的IMAGEVIEW控件  

ImageLoader.getInstance().displayImage(imageUrl, imageView);

2.加載自定義配置的一個圖片的

 // imageUrl代表圖片的URL地址,imageView代表承載圖片的IMAGEVIEW控件 , options代表DisplayImageOptions配置文件  

ImageLoader.getInstance().displayImage(imageUrl, imageView,options);
圖片加載時候帶加載情況的監聽
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {  
    @Override  
    public void onLoadingStarted() {  
       //開始加載的時候執行  
    }  
    @Override  
    public void onLoadingFailed(FailReason failReason) {        
       //加載失敗的時候執行  
    }   
    @Override   
    public void onLoadingComplete(Bitmap loadedImage) {  
       //加載成功的時候執行  
    }   
    @Override   
    public void onLoadingCancelled() {  
       //加載取消的時候執行  

    }});  
圖片加載時候,帶監聽又帶加載進度條的情況
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {  
    @Override  
    public void onLoadingStarted() {  
       //開始加載的時候執行  
    }  
    @Override  
    public void onLoadingFailed(FailReason failReason) {        
       //加載失敗的時候執行  
    }      
    @Override      
    public void onLoadingComplete(Bitmap loadedImage) {  
       //加載成功的時候執行  
    }      
    @Override      
    public void onLoadingCancelled() {  
       //加載取消的時候執行  
    },new ImageLoadingProgressListener() {        
      @Override  
      public void onProgressUpdate(String imageUri, View view, int current,int total) {     
      //在這裡更新 ProgressBar的進度信息  
      }  
    });  

如何加載本地圖片:正確配置 ImageUrl 的地址即可

String imageUri = "http://site.com/image.png"; // from Web  
String imageUri = "file:///mnt/sdcard/image.png"; // from SD card  
String imageUri = "content://media/external/audio/albumart/13"; // from content provider  
String imageUri = "assets://image.png"; // from assets  
String imageUri = "drawable://" + R.drawable.image; // from drawables (only images, non-9patch)  

xUtils 異步框架的使用


github: https://github.com/wyouflf/xUtils3

xUtils3簡介

xUtils 包含了很多實用的android工具. xUtils 支持超大文件(超過2G)上傳,更全面的http請求協議支持(11種謂詞),擁有更加靈活的ORM,更多的事件注解支持且不受混淆影響… xUtils 最低兼容Android 4.0 (api level 14). (Android 2.3?) xUtils3變化較多所以建立了新的項目不在舊版(github.com/wyouflf/xUtils)上繼續維護, 相對於舊版本:
HTTP實現替換HttpClient為UrlConnection, 自動解析回調泛型, 更安全的斷點續傳策略. 支持標准的Cookie策略, 區分domain, path… 事件注解去除不常用的功能, 提高性能. 數據庫api簡化提高性能, 達到和greenDao一致的性能. 圖片綁定支持gif(受系統兼容性影響, 部分gif文件只能靜態顯示), webp; 支持圓角, 圓形, 方形等裁剪, 支持自動旋轉…

使用Gradle構建時添加一下依賴即可:

compile 'org.xutils:xutils:3.3.36'

使用前配置

需要的權限

初始化
// 在application的onCreate中初始化
@Override
public void onCreate() {
    super.onCreate();
    x.Ext.init(this);
    x.Ext.setDebug(BuildConfig.DEBUG); // 是否輸出debug日志, 開啟debug會影響性能.
    ...
}

加載圖片

最簡單的使用默認配置加載圖片

x.image().bind(imageView,imageUrl);//使用xUtils加載圖片,默認自帶緩存

x.image().bind() 方法有多個重載函數,這一點和ImageLoader 很相似

void bind(ImageView view, String url);

void bind(ImageView view, String url, ImageOptions options);

void bind(ImageView view, String url, Callback.CommonCallback callback);

void bind(ImageView view, String url, ImageOptions options, Callback.CommonCallback callback);

使用示例:

 ImageOptions options = new ImageOptions.Builder()

                      .setSize(DensityUtil.dip2px(120), DensityUtil.dip2px(120))//圖片大小
                      .setRadius(DensityUtil.dip2px(5))//ImageView圓角半徑
                      .setCrop(true)// 如果ImageView的大小不是定義為wrap_content, 不要crop.
                      .setImageScaleType(ImageView.ScaleType.CENTER_CROP)
                      .setLoadingDrawableId(R.mipmap.ic_launcher)//加載中默認顯示圖片
                      .setFailureDrawableId(R.mipmap.ic_launcher)//加載失敗後默認顯示圖片



                      .build();

              x.image().bind(imageView,imageUrl);//使用xUtils加載圖片,默認自帶緩存
              x.image().bind(imageView,imageUrl,options,new MyCallBack());


 /**
     * 加載圖片時的回調函數
     */
    class MyCallBack implements Callback.CommonCallback {

    @Override
    public void onSuccess(Object result) {
        System.out.println("加載圖片"+"onSuccess()");

    }

    @Override
    public void onError(Throwable ex, boolean isOnCallback) {

    }

    @Override
    public void onCancelled(CancelledException cex) {

    }

    @Override
    public void onFinished() {
        System.out.println("加載圖片"+"onFinished()");

    }

xUtils的網絡請求

 RequestParams params = new RequestParams("http://blog.csdn.net/mobile/experts.html");
                x.http().get(params, new Callback.CommonCallback() {
                    @Override
                    public void onSuccess(String result) {
                        System.out.println("網絡請求onSuccess()...");

                        text.setText(result);
                    }

                    @Override
                    public void onError(Throwable ex, boolean isOnCallback) {

                    }

                    @Override
                    public void onCancelled(CancelledException cex) {

                    }

                    @Override
                    public void onFinished() {
                        System.out.println("網絡請求onFinished()...");
                    }
                });

帶有緩存的請求示例:

   RequestParams params = new RequestParams("http://blog.csdn.net/mobile/experts.html");
                // 默認緩存存活時間, 單位:毫秒.(如果服務沒有返回有效的max-age或Expires)
                params.setCacheMaxAge(1000 * 60 * 10);
                // 接下來使用CacheCallback, xUtils將為該請求緩存數據.
                x.http().get(params, new Callback.CacheCallback() {
                    @Override
                    public boolean onCache(String result) {
                        // 得到緩存數據, 緩存過期後不會進入這個方法.
                        // 如果服務端沒有返回過期時間, 參考params.setCacheMaxAge(maxAge)方法.
                        //
                        // * 客戶端會根據服務端返回的 header 中 max-age 或 expires 來確定本地緩存是否給 onCache 方法.
                        //   如果服務端沒有返回 max-age 或 expires, 那麼緩存將一直保存, 除非這裡自己定義了返回false的
                        //   邏輯, 那麼xUtils將請求新數據, 來覆蓋它.
                        //
                        // * 如果信任該緩存返回 true, 將不再請求網絡;----這裡可以和刷新配合使用
                        //   返回 false 繼續請求網絡, 但會在請求頭中加上ETag, Last-Modified等信息,
                        //   如果服務端返回304, 則表示數據沒有更新, 不繼續加載數據.
                        //
                        text.setText(result);
                        return false; // true: 信任緩存數據, 不在發起網絡請求; false不信任緩存數據.
                    }

                    @Override
                    public void onSuccess(String result) {
                        // 注意: 如果服務返回304 或 onCache 選擇了信任緩存, 這時result為null.
                        if (result != null) {
                            text.setText(result);
                        }
                    }

                    @Override
                    public void onError(Throwable ex, boolean isOnCallback) {

                    }

                    @Override
                    public void onCancelled(CancelledException cex) {

                    }

                    @Override
                    public void onFinished() {

                            // 成功獲取數據,在此方法中對返回的數據進行操作

                    }
                });
            }
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved