本篇博文接上篇的《Android項目開發全程(一)--創建工程》,主要介紹一下在本項目中用到的一個很重要的框架-Afinal,由於本系列博文重點是項目開發全程,所以在這里就先介紹一下本項目中用到的幾個功能:
Afinal簡介
- Afinal 是一個android的sqlite orm 和 ioc 框架。同時封裝了android中的http框架,使其更加簡單易用;
- 使用finalBitmap,無需考慮bitmap在android中加載的時候oom的問題和快速滑動的時候圖片加載位置錯位等問題。
- Afinal的宗旨是簡潔,快速。約定大於配置的方式。盡量一行代碼完成所有事情。
Afinal的四大模塊
-
FinalDB模塊:android中的orm框架,一行代碼就可以進行增刪改查。支持一對多,多對一等查詢。
-
FinalActivity模塊:android中的ioc框架,完全注解方式就可以進行UI綁定和事件綁定。無需findViewById和setClickListener等。
-
FinalHttp模塊:通過httpclient進行封裝http數據請求,支持ajax方式加載。
-
FinalBitmap模塊:通過FinalBitmap,imageview加載bitmap的時候無需考慮bitmap加載過程中出現的oom和android容器快速滑動時候出現的圖片錯位等現象。FinalBitmap可以配置線程加載線程數量,緩存大小,緩存路徑,加載顯示動畫等。FinalBitmap的內存管理使用lru算法,沒有使用弱引用(android2.3以后google已經不建議使用弱引用,android2.3后強行回收軟引用和弱引用,詳情查看android官方文檔),更好的管理bitmap內存。FinalBitmap可以自定義下載器,用來擴展其他協議顯示網絡圖片,比如ftp等。同時可以自定義bitmap顯示器,在imageview顯示圖片的時候播放動畫等(默認是漸變動畫顯示)。
使用Afinal開發框架需要用到以下權限
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
以上是github上的Afinal整體介紹,下面介紹一下本項目中需要到的幾個功能,由於本次項目很小,僅僅用到了Afinal中的一點點功能:
1、注解方式就可以進行UI綁定和事件綁定,無需使用findViewById和setClickListener等方法,別忘了讓Activity繼承FinalActivity。
1 public class TestActivity extends FinalActivity { 2 @ViewInject(id=R.id.bn_click, click="testClick") Button bnClick; 3 @ViewInject(id=R.id.tv_show) TextView tvShow; 4 @Override 5 protected void onCreate(Bundle savedInstanceState) { 6 // TODO Auto-generated method stub 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.test_main); 9 } 10 public void testClick(View v){ 11 tvShow.setText("您點擊了確定"); 12 } 13 }
運行結果:
點擊確定后->
2、FinalHttp的使用,接下來就要開掛了,還是用剛才的Activity,稍作修改讓我們來做一下網絡請求
get方法: 一行代碼搞定,直接使用get方法提交請求地址,然后在相關的回調方法中進行結果操作。上面代碼給出了三個回調方法
1 public class TestActivity extends FinalActivity { 2 FinalHttp fh; 3 String url = "http://xiaohua.hao.360.cn/m/itxt?page=1"; 4 @ViewInject(id=R.id.bn_click, click="testClick") Button bnClick; 5 @ViewInject(id=R.id.tv_show) TextView tvShow; 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 // TODO Auto-generated method stub 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.test_main); 11 fh = new FinalHttp(); 12 } 13 public void testClick(View v){ 14 fh.get(url, new AjaxCallBack<String>(){ 15 @Override 16 public void onStart() { 17 // TODO Auto-generated method stub 18 super.onStart(); 19 tvShow.setText("正在請求……"); 20 } 21 22 @Override 23 public void onLoading(long count, long current) { 24 // TODO Auto-generated method stub 25 super.onLoading(count, current); 26 //請求響應過程中會執行此方法,每隔1秒自動回調一次 27 tvShow.setText(current + "/" + count); 28 } 29 30 @Override 31 public void onSuccess(String t) { 32 // TODO Auto-generated method stub 33 super.onSuccess(t); 34 tvShow.setText(t); 35 } 36 37 @Override 38 public void onFailure(Throwable t, int errorNo, String strMsg) { 39 // TODO Auto-generated method stub 40 super.onFailure(t, errorNo, strMsg); 41 tvShow.setText("網絡異常"); 42 } 43 }); 44 } 45 }
post方法:
1 AjaxParams params = new AjaxParams(); 2 params.put("username", "testname"); 3 params.put("password", "123456"); 4 params.put("profile_picture", new File("/mnt/sdcard/test.jpg")); // 上傳文件 5 params.put("profile_picture2", inputStream); // 上傳數據流 6 params.put("profile_picture3", new ByteArrayInputStream(bytes)); // 提交字節流 7 8 fh.post("http://www.test.com", params, new AjaxCallBack(){......});
① onStart()請求開始時回調此方法。
② onSuccess()請求成功時回調此方法,其中“t”為返回結果。
③ onFailure()請求失敗時回調此方法。
④ onLoading()在請求響應過程中,每隔1秒回調一次此方法。
執行結果如下:
3、FinalBitmap的使用。同樣,加載網絡圖片也是就一行代碼 fb.display(imageView,url)。
1 public void loadingImg(View v){ 2 FinalBitmap fb = FinalBitmap.create(this); 3 fb.display(ivImg, "http://pic4.nipic.com/20091120/805653_183746006558_2.jpg"); 4 }
其中,loadingImg方法是用注解方式綁定在按鈕上的事件,ivImg是ImageView控件。點擊按鈕后就會加載一張網絡圖片,結果如下:
哈哈,是不是很簡單,同時也很給力啊!
本項目目前設計到Afinal的一些用法就這幾個,如果想了解更多可以參考:http://www.oschina.net/p/afinal
在項目開中還涉及到了另一個很給力的工具--Jackson,暫時先不介紹了,等在項目中需要到的時候再做介紹。
有了這兩樣工具,我們的開發工作就大大簡化了很多,而且性能絕不比自己純手工去寫網絡請求之類的方法性能差。當然,在實際的開發中我們不能這樣暴力式的直接使用get和post方法,最好是做一下封裝,這樣的話既節省了工作量,減少重復代碼,又保證了請求方式的規范性,在后續博文中會展開項目的詳細介紹。
PS:本來打算只介紹上面這么多呢,因為在將要介紹到的項目中目前只用到上面這幾個功能,不過有園友建議再介紹一下FinalDb,OK,再續上一段。
4、FinalDb的使用。
其實用Afinal操作數據也是非常方便的,仍然很好的體現着Afinal的風格,一行代碼實現保存數據/讀取數據。
首先建立一個實體對象,用來充當數據表角色。
1 public class Note { 2 private int id;//id屬性必須要有 3 private String title; 4 private String content; 5 6 /* getter and setter方法一定要有,應為FinalDb會通過setter方法賦值*/ 7 public int getId() { 8 return id; 9 } 10 public String getTitle() { 11 return title; 12 } 13 public String getContent() { 14 return content; 15 } 16 public void setId(int id) { 17 this.id = id; 18 } 19 public void setTitle(String title) { 20 this.title = title; 21 } 22 public void setContent(String content) { 23 this.content = content; 24 } 25 }
實體類建好了,再寫一個測試Activity:
1 public class DbTestActivity extends FinalActivity { 2 FinalDb fd; 3 Note note; 4 @ViewInject(id=R.id.et_title) EditText etTitle; 5 @ViewInject(id=R.id.et_content) EditText etContent; 6 @ViewInject(id=R.id.txt_title) TextView txtTitle; 7 @ViewInject(id=R.id.txt_content) TextView txtContent; 8 @ViewInject(id=R.id.bn_save, click="saveData") Button bnSave; 9 @ViewInject(id=R.id.bn_read, click="readData") Button bnRead; 10 @Override 11 protected void onCreate(Bundle savedInstanceState) { 12 // TODO Auto-generated method stub 13 super.onCreate(savedInstanceState); 14 setContentView(R.layout.activity_dbtest); 15 fd = FinalDb.create(this); 16 } 17 18 //利用Afinal注解直接在按鈕上綁定事件。 19 public void saveData(View v){ 20 dbSave(); 21 } 22 23 public void readData(View v){ 24 dbRead(); 25 } 26 27 private void dbSave(){ 28 note = new Note(); 29 note.setTitle(etTitle.getText().toString()); 30 note.setContent(etContent.getText().toString()); 31 //利用FinalDb的save方法保存數據 32 fd.save(note); 33 } 34 35 private void dbRead(){ 36 //利用FinalDb的findAll方法查詢數據 37 List<Note> noteList = fd.findAll(Note.class); 38 txtTitle.setText("標題:" + noteList.get(0).getTitle()); 39 txtContent.setText("內容:" + noteList.get(0).getContent()); 40 } 41 }
布局文件也很簡單,也一並貼出來吧。
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:id="@+id/container" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:orientation="vertical"> 7 8 <EditText 9 android:id="@+id/et_title" 10 android:layout_width="match_parent" 11 android:layout_height="wrap_content" 12 android:hint="Input title" 13 android:ems="10" > 14 <requestFocus /> 15 </EditText> 16 17 <EditText 18 android:id="@+id/et_content" 19 android:layout_width="match_parent" 20 android:layout_height="wrap_content" 21 android:hint="Input content" 22 android:ems="10" > 23 </EditText> 24 25 <Button 26 android:id="@+id/bn_save" 27 android:layout_width="fill_parent" 28 android:layout_height="wrap_content" 29 android:text="保存到數據庫" /> 30 31 <Button 32 android:id="@+id/bn_read" 33 android:layout_width="fill_parent" 34 android:layout_height="wrap_content" 35 android:text="讀取數據" /> 36 37 <TextView 38 android:id="@+id/txt_title" 39 android:layout_width="wrap_content" 40 android:layout_height="wrap_content" 41 android:text="標題:" /> 42 43 <TextView 44 android:id="@+id/txt_content" 45 android:layout_width="wrap_content" 46 android:layout_height="wrap_content" 47 android:text="內容:" /> 48 49 </LinearLayout>
執行結果如圖,在編輯框輸入內容后,單擊保存到數據庫按鈕,程序會執行fd.save方法(如左圖),然后我們單擊讀取數據按鈕,就會從數據庫中讀取出來數據,並顯示在下面(如右圖)
然后我們在驗證一下,是否真的插入了數據庫,關閉程序,重新打開后直接點擊讀取數據按鈕,會看到仍然可以讀取之前保存過的內容,由於在代碼中,只取了數據表中的第一行內容,所以多次保存后仍然只顯示第一次寫入的數據。(由於手機目前沒有root,所以無法直接通過eclipse的File Explorer查看數據庫,敬請諒解!)
以上只是簡單介紹了一下Afinal的幾個用法,希望能起到拋磚引玉的作用,好了,步入正題,在下一遍博文中將要開始咱們的項目之旅......