xUtils框架

yangxi_001發表於2015-01-16

微信賬號申請終於通過了,這是我們第一次Android乾貨分享。想來是第一次,要對得起“乾貨”二字。今天我要為大家推薦的是一個Android基於快速開發的一個框架——xUtils,它是在aFinal基礎上進行重構和擴充套件的框架,相比aFinal有很大的改善。同時,如果如果你的應用是基於網路的,那麼只要處理得當,它會讓你徹底的擺脫各種工具類和重複程式碼的困擾。好的,廢話不多說,程式猿們還是程式碼說起。

    xUtils 包含了很多實用的android工具。xUtils 源於Afinal框架,對Afinal進行了大量重構,使得xUtils支援大檔案上傳,更全面的http請求協議支援,擁有更加靈活的ORM,更多的事件註解支援且不受混淆影響。同時需要注意的是,xUitls最低相容android 2.2 (api level 8)  。今天我們的主題是整體介紹下xUtils,主要介紹它重要的四大元件。具體各個元件的使用,會在之後幾天陸續為大家奉上。下面開始:

一、ViewUtils

        你受夠了重複冗長的findViewById了嘛?你受夠了各種監聽事件的繫結了嘛?在這裡,你只需要一句註解,如@ViewInject、@OnClick,就能輕鬆擺脫小白似的程式碼,大大的上了一個檔次。

二、HttpUtils

       支援的HTTP七種請求方式,非常便捷的滿足你的介面請求的需要。同時還支援大檔案上傳下載,以及同步非同步請求。

三、BitmapUtils

       你的程式因OOM強制關閉過嘛?你在為加在網路圖片頭疼嘛?有了元件,你將永久擺脫前面的問題。

四、DbUtils

       簡單易用又出色的ORM框架,真的是誰用誰知道,直接輕鬆儲存各種物件到sqlite資料庫中,同時也能非常方便的進行各種條件查詢,甚至分頁查詢,還有對錶中資料的更新刪除等操作,真正的實現。一行程式碼就可以進行增刪改查。並且可通過註解自定義表名,列名,外來鍵,唯一性約束,NOT NULL約束,CHECK約束等,支援事務。

    由於xUtils是基於aFinal的,這個開源框架是國內的某位大神寫的,所以瞭解了aFinal之後再回頭看xUtils,才會更有收穫。同時,也要向這位大神以及眾多的開源貢獻者致敬,有了他們的奉獻和開源的精神,才湧現出一個個耳熟能詳的更加優秀的更加穩定的框架。我們眾所周知的Linux就是這麼誕生的。

        aFinal學習地址:http://www.afinal.org

昨天對xUtils整體上做了一個簡單的介紹,今天我們們就程式碼碼起,真刀實槍的也看看,看看如何快速便捷的把xUtils給整合到大家的專案中去。xUtils中有四大元件可以供我們使用,分別是ViewUtils、HttpUtils、BitmapUtils以及DbUtils。如果你沒能先讀一下我的上一篇文章,那麼請你移步過去先整體瞭解一下,再回過頭來看這篇文章,相信你回更有體會的。

下面依次開始介紹這些元件具體的使用。

一、ViewUtils  android中得ioc(控制反轉)框架,可以完全使用註解的方式來完成UI的繫結和事件繫結。簡單的說,ViewUtils的功能就是做這個的,但是可以說,就這麼個功能確是能極大的簡化我們的程式碼。下面我們看下具體的程式碼,順便對比下註解的方式繫結ID和findViewById之間的差別。

[java] view plaincopy
  1. <span style="white-space:pre">  </span>@ViewInject(R.id.btn)  
  2.     private Button btn;  
  3.       
  4.     @ViewInject(R.id.img)  
  5.     private ImageView img;  
  6.       
  7.     @ViewInject(R.id.list)  
  8.     private ListView list;  
  9.       
  10.     @Override  
  11.     protected void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.activity_second);  
  14.         ViewUtils.inject(this);}  


[java] view plaincopy
  1. <p style="margin-top:0px; margin-bottom:0px; font-size:14px; font-family:Monaco; color:rgb(119,119,119)"></p>  
[java] view plaincopy
  1.   
[java] view plaincopy
  1. <span style="white-space:pre">  </span>@Override  
  2.     protected void onCreate(Bundle savedInstanceState) {  
  3.         super.onCreate(savedInstanceState);  
  4.         setContentView(R.layout.activity_second);  
  5.           
  6.         btn = (Button) findViewById(R.id.btn);  
  7.         img = (ImageView) findViewById(R.id.img);  
  8.         list = (ListView) findViewById(R.id.list);  
  9.           
  10.     }  


如果專案中得Activity中的控制元件相當多,那麼想象一下程式碼中累積的那一大坨就真心受不了。通過xUtils的簡單註解,就能輕鬆擺脫無盡壞味道的程式碼。

注意:在使用註解繫結控制元件的時候,一定記得在onCreate中呼叫ViewUtils.inject(this);

下面我們再對比下Android中事件繫結的區別。

[java] view plaincopy
  1. <span style="white-space:pre">  </span>@OnClick({ R.id.btn, R.id.img })  
  2.     public void clickMethod(View v) {  
  3.         Toast.makeText(SecondActivity.this"you clicked button!",  
  4.                 Toast.LENGTH_SHORT).show();  
  5.     }  
  6.   
  7.     @OnItemClick(R.id.list)  
  8.     public void itemClick(AdapterView<?> parent, View view, int position,long id) {  
  9.         Toast.makeText(SecondActivity.this"position--->" + position,  
  10.                 Toast.LENGTH_SHORT).show();  
  11.     }  

[java] view plaincopy
  1. <span style="white-space:pre">      </span>btn.setOnClickListener(this);  
  2.         list.setOnItemClickListener(new OnItemClickListener() {  
  3.             @Override  
  4.             public void onItemClick(AdapterView<?> parent, View view,  
  5.                     int position, long id) {  
  6.                 Toast.makeText(SecondActivity.this"position--->" + position,  
  7.                         Toast.LENGTH_SHORT).show();  
  8.             }  
  9.         });<pre name="code" class="java"><span style="white-space:pre"> </span>@Override  
  10.     public void onClick(View v) {  
  11.         switch (v.getId()) {  
  12.         case R.id.btn:  
  13.             Toast.makeText(SecondActivity.this"you clicked button!",  
  14.                     Toast.LENGTH_SHORT).show();  
  15.             break;  
  16.         default:  
  17.             break;  
  18.         }  
  19.     }</pre><br>  
原本繫結Button的監聽事件要麼用醜陋的內部類,要麼Activity實現OnClickListener,在複寫的onClick方法中去根據id。而xUtils只要通過簡單的一句註解就能實現監聽事件的功能,而且可以實現多個控制元件共用一個監聽方法。同時xUtils提供onClick、onItemClick、onLongClick等15種事件監聽註解。

注意:在使用註解監聽事件的時候,監聽方法名是自定義的,但是一定要保證方法的訪問修飾符為public,同時方法的引數要與Android原來的監聽方法引數一致,不僅引數型別,而且要保證引數的順序。

二、BitmapUtils  載入網路或本地bitmap的時候無需擔心再遇到OOM的現象,管理bitmap的記憶體採用了LRU演算法,同時也能避免列表滑動過程中發生圖片錯位等得現象。載入網路圖片時,還可以配置執行執行緒的數量,快取路徑等。。。通過BitmapUtils的各種構造器,可以很方便的建立出本地快取路徑和快取的大小,以及記憶體快取的大小。

[java] view plaincopy
  1. <span style="white-space:pre">  </span>BitmapUtils utils = new BitmapUtils(this);  
  2.     BitmapDisplayConfig config = new BitmapDisplayConfig(this);  
  3.     config.setLoadingDrawable(getResources().getDrawable(R.drawable.loading));  
  4.     config.setLoadFailedDrawable(getResources().getDrawable(R.drawable.failed));  
  5.     config.setImageLoadCallBack(new ImageLoadCallBack() {  
  6.         @Override  
  7.         public void loadFailed(ImageView imageView, Drawable drawable) {  
  8.         }  
  9.         @Override  
  10.         public void loadCompleted(ImageView imageView, Drawable drawable,  
  11.                 BitmapDisplayConfig config) {  
  12.         }  
  13.     });  
  14.     config.setBitmapMaxWidth(480);  
  15.     config.setBitmapMaxHeight(720);  
  16. /       utils.display(img, "http://img1.gtimg.com/news/pics/hv1/63/26/1451/94357968.jpg");  
  17.     utils.display(img, "http://img1.gtimg.com/news/pics/hv1/63/26/1451/94357968.jpg", config);  

BitmapUtils在用來載入網路圖片時,可以配置載入圖片尺寸的大小,載入成功和失敗的回撥以及載入過程中圖片的配置。同時也可以選擇不配置。

[java] view plaincopy
  1. //bitmapUtils.display(testImageView, "/sdcard/test.jpg"); //支援載入本地圖片  
  2.   
  3. // 使用ListView等容器展示圖片時可通過PauseOnScrollListener控制滑動和快速滑動過程中時候暫停載入圖片  
  4. listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, falsetrue));  
  5. listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, falsetrue), customListener);  

接上回,繼續介紹xUtils的最後兩個模組:DbUtils和HttpUtils。首先先介紹第一個SQLite資料庫操縱的簡單ORM框架,只要能理解xUtils為我們提供的api,相信你也能熟練的把DbUtils用到專案中去。

操縱資料庫的工具類,無論多牛X,總離不開最根本的CRUD,即建立,查詢,更新和刪除。下面從這四個角度依次介紹xUtils是如何簡便持久化資料的。大家都知道,在Android裡面如果要儲存一個物件,我們需要建立一個SQLiteOpenHelper,然後還得建立一張對應物件各個屬性的表,還得繼續把我們的物件轉換成ContentValues,進而去儲存。真心是麻煩的不能再麻煩了,我們現在介紹的DbUtils就能讓你輕鬆解脫麻繩一樣的程式碼。DbUtils在進行save操作的時候,會根據java反射反射出物件的各個欄位,然後去查詢資料庫中是否存在這個物件型別對應的表,如果表已經存在,直接進行插入操作;如果不存在,就先動態的建立的一張對應我們物件的表,再進行插入處理。直接上程式碼,大家看。

[java] view plaincopy
  1. <span style="white-space:pre">  </span>@OnClick(R.id.insert)  
  2.     public void insert(View v) {  
  3.         Student stu = null;  
  4.         for (int i = 0; i < 20; i++) {  
  5.             stu = new Student();  
  6.             stu.setAge(10 + i);  
  7.             stu.setName("jack" + i);  
  8.             mList.add(stu);  
  9.             try {  
  10.                 dbUtils.save(stu);  
  11.             } catch (DbException e) {  
  12.                 e.printStackTrace();  
  13.             }  
  14.         }  
  15.     }  
注意:並不是所有的實體物件都快可以通過這種方式去儲存,一定要保證物件的型別中有int型別的id或者_id的屬性,這就對應資料庫表中的主鍵欄位。如果型別中沒有id欄位,可以通過@Id註解去指定一個int型別的欄位作為主鍵。如果表中的又欄位不想被儲存在資料庫中,也可以通過@Transient去實現忽略。如果直接儲存一個物件的列表,這樣也是被允許的,達到批量儲存的目的。

DbUtils可以幫助對SQL語句不是很熟悉的同學快速的實現查詢,而不用去寫sql查詢語句,而且可以對查詢結果進行排序和分頁,使用簡單,功能強大。大家可以看下,下面的幾行程式碼就能實現複雜的查詢功能

[java] view plaincopy
  1. <span style="white-space:pre">  </span>dbUtils.findAll(Selector.from(Student.class)  
  2. <span style="white-space:pre">      </span>.where("_id""<"10).and("age"">"10).orderBy("_id")  
  3. <span style="white-space:pre">      </span>.limit(pageSize).offset(pageSize * pageIndex));  
同樣的,也可以對資料庫中得資料進行便捷的更新。下面演示的是更新Student對應的表中的第一條記錄的age這個欄位。這個比較簡單,就直接上程式碼看吧。

[java] view plaincopy
  1. <span style="white-space:pre">  </span>@OnClick(R.id.update)  
  2.     public void update(View v){  
  3.         try {  
  4.             List<Student> stus = dbUtils.findAll(Selector.from(Student.class));  
  5.             Student stu = stus.get(0);  
  6.             stu.setAge(20);  
  7.             dbUtils.update(stu);  
  8.         } catch (DbException e) {  
  9.             e.printStackTrace();  
  10.         }  
  11.     }  

最後一個就是資料的刪除。一個實體物件,一組實體物件,根據條件刪除,刪除表,刪除整個資料庫,這些操作都可以通過一句簡單的程式碼來實現,看了程式碼就明白了。

[java] view plaincopy
  1. @OnClick(R.id.delete)  
  2. public void delete(View v){  
  3.     try {  
  4.         List<Student> stus = dbUtils.findAll(Selector.from(Student.class));  
  5.         dbUtils.delete(stus.get(0));  
  6.         dbUtils.deleteAll(stus);  
  7.         dbUtils.deleteById(Student.class, WhereBuilder.b("age""=="20));  
  8.         dbUtils.dropTable(Student.class);  
  9.         dbUtils.dropDb();  
  10.     } catch (DbException e) {  
  11.         e.printStackTrace();  
  12.     }  
  13. }  

今天介紹xUtils的最後一個模組——HttpUtils,拖了那麼久,終於要結束了。另外,碼字不易,如果大家有什麼疑問和見解,歡迎大家留言討論。HttpUtils是解決日常工作過程中繁雜的上傳下載檔案以及各種Get和post請求的必備工具類,通過這個類,開源非常方便關注介面的業務,不必再再寫那麼冗長的程式碼。下面全文都圍繞著四個中心點去依次展開,分別是:HttpGet請求,HttpPost請求,下載檔案和上傳檔案。

HttpGet請求。相信從事Android網路應用的開發的同學對這個一定不會陌生,長期的開發會讓大家積累下一個可以複用的工具類。而xUtils就是幫助了我們把那些工具類給抽象整合成一個更具擴充套件性的幫助類。比如HtttpGet請求,這裡只簡要介紹下關鍵的應用方法,具體的細節還請大家自己去下載xUtils的原始碼去研究研究了,我們介紹的足夠應用到我們的應用開發中去了。通常的HttpGet請求會把一系列的請求引數掛在請求地址的後面,拖出一節長長的尾巴,十分的惹人厭,這裡可以通過像HttpPost請求的引數那樣組成一個類似BasicNameValuePair的物件直接封裝到請求方法中去,省去拼接url的麻煩,同時也可以設定超時時間。另外請求的方法中提供了一個回撥類,這個類中有處理不同請求結果的回撥方法,比如說請求過程中的回撥,請求成功的回撥以及請求出現錯誤時的回撥。下面直接上程式碼看下。

[java] view plaincopy
  1. RequestParams params = new RequestParams();  
  2.      params.addQueryStringParameter("method""info");  
  3.      params.addQueryStringParameter("access_token",  
  4.              "3.1042851f652496c9362b1cd77d4f849b.2592000.1377530363.3590808424-248414");  
  5.   
  6.      HttpUtils http = new HttpUtils();  
  7.      http.configCurrentHttpGetCacheExpiry(1000 * 10);  
  8.      http.send(HttpRequest.HttpMethod.GET,  
  9.              "https://pcs.baidu.com/rest/2.0/pcs/quota",  
  10.              params,  
  11.              new RequestCallBack<String>() {  
  12.   
  13.                  @Override  
  14.                  public void onStart() {  
  15.                      resultText.setText("conn...");  
  16.                  }  
  17.   
  18.                  @Override  
  19.                  public void onLoading(long total, long current) {  
  20.                      resultText.setText(current + "/" + total);  
  21.                  }  
  22.   
  23.                  @Override  
  24.                  public void onSuccess(String result) {  
  25.                      resultText.setText("response:" + result);  
  26.                  }  
  27.   
  28.   
  29.                  @Override  
  30.                  public void onFailure(HttpException error, String msg) {  
  31.                      resultText.setText(msg);  
  32.                  }  
  33.              });  

HttpPost請求。為了統一請求的風格,HttpPost請求的方式和HttpGet的幾乎可以說是一模一樣,一樣提供了各種對應不同結果的回撥方法,大家自己看下面的程式碼就曉得了,真是一目瞭然。

[java] view plaincopy
  1. RequestParams params = new RequestParams();  
  2.        params.addQueryStringParameter("method""mkdir");  
  3.        params.addQueryStringParameter("access_token""3.1042851f652496c9362b1cd77d4f849b.2592000.1377530363.3590808424-248414");  
  4.        params.addBodyParameter("path""/apps/測試應用/test資料夾");  
  5.   
  6.        HttpUtils http = new HttpUtils();  
  7.        http.send(HttpRequest.HttpMethod.POST,  
  8.                "https://pcs.baidu.com/rest/2.0/pcs/file",  
  9.                params,  
  10.                new RequestCallBack<String>() {  
  11.   
  12.                    @Override  
  13.                    public void onStart() {  
  14.                        resultText.setText("conn...");  
  15.                    }  
  16.   
  17.                    @Override  
  18.                    public void onLoading(long total, long current) {  
  19.                        resultText.setText(current + "/" + total);  
  20.                    }  
  21.   
  22.                    @Override  
  23.                    public void onSuccess(String result) {  
  24.                        resultText.setText("upload response:" + result);  
  25.                    }  
  26.   
  27.   
  28.                    @Override  
  29.                    public void onFailure(HttpException error, String msg) {  
  30.                        resultText.setText(msg);  
  31.                    }  
  32.                });  

下面為大家介紹一個非常非常實用的功能,就是通過Http協議去下載檔案,再也不必為Android中下載檔案而寫下一大坨一大坨的程式碼,如此長的程式碼除錯起來真是能氣死人。還記得以前做過一個專案,有個需求就是能下載視訊的,而且還要能支援斷點下載,只寫那麼一個下載工具類就寫了一兩天,再加上除錯,真心把人都給逼瘋了。要是xUtils早點在那個時候面世,想那時做那個需求也不必那麼通過。HttpUtils為開發者提供了非常方便的下載api,可以通過簡單的幾個引數來實現下載,甚至斷點下載的功能。上程式碼。

[java] view plaincopy
  1. <span style="white-space:pre">  </span>HttpHandler  handler = http.download(  
  2.                 downloadAddrEdit.getText().toString(),  
  3.                 "/sdcard/fileexplorer.apk",  
  4.                 true// 如果目標檔案存在,接著未完成的部分繼續下載。  
  5.                 true// 如果從請求返回資訊中獲取到檔名,下載完成後自動重新命名。  
  6.                 new RequestCallBack<File>() {   
  7.   
  8.                     @Override  
  9.                     public void onStart() {  
  10.                         resultText.setText("conn...");  
  11.                     }  
  12.   
  13.                     @Override  
  14.                     public void onLoading(long total, long current) {  
  15.                         resultText.setText(current + "/" + total);  
  16.                     }  
  17.   
  18.                     @Override  
  19.                     public void onSuccess(File result) {  
  20.                         resultText.setText("downloaded:" + result.getPath());  
  21.                     }  
  22.   
  23.                     @Override  
  24.                     public void onFailure(HttpException error, String msg) {  
  25.                         resultText.setText(error.getExceptionCode() + ":" + msg);  
  26.                     }  
  27.                 });  
注意:下載過程中如果需要暫停下載,也只需簡單的一行程式碼來實現:mHandler.stop(),如果設定斷點下載的話,下次會重新開始的話,會自動從上次下載的斷點處繼續下載。


最後介紹的功能就是上傳檔案了,這個也是在專案中也是非常常見的。比如使用者上傳頭像,再比如網盤應用需要把本地檔案上傳到雲端等等。同時HttpUtils也同時為開發者提供了上傳過程中和上傳結果的各個回撥介面。大家在使用HttpUtils上傳檔案的時候,只要仿照下面的程式碼去碼程式碼就快可以基本滿足業務的需要了。

[java] view plaincopy
  1. <strong> </strong>RequestParams params = new RequestParams();  
  2.         params.addQueryStringParameter("method""upload");  
  3.         params.addQueryStringParameter("path""/apps/測試應用/test.zip");  
  4.         // 請在百度的開放access_tokenapi測試頁面找到自己的access_token  
  5.         params.addQueryStringParameter("access_token""3.1042851f652496c9362b1cd77d4f849b.2592000.1377530363.3590808424-248414");  
  6.         params.addBodyParameter("file"new File("/sdcard/test.zip"));  
  7.   
  8.         HttpUtils http = new HttpUtils();  
  9.         http.send(HttpRequest.HttpMethod.POST,  
  10.                 "https://pcs.baidu.com/rest/2.0/pcs/file",  
  11.                 params,  
  12.                 new RequestCallBack<String>() {  
  13.   
  14.                     @Override  
  15.                     public void onStart() {  
  16.                         resultText.setText("conn...");  
  17.                     }  
  18.   
  19.                     @Override  
  20.                     public void onLoading(long total, long current) {  
  21.                         resultText.setText(current + "/" + total);  
  22.                     }  
  23.   
  24.                     @Override  
  25.                     public void onSuccess(String result) {  
  26.                         resultText.setText("upload response:" + result);  
  27.                     }  
  28.   
  29.   
  30.                     @Override  
  31.                     public void onFailure(HttpException error, String msg) {  
  32.                         resultText.setText(msg);  
  33.                     }  
  34.                 });  

相關文章