1. 程式人生 > >[android]Xutils具體介紹

[android]Xutils具體介紹

istview cat enc 下載 cti 獲取 object all target

什麽是Xutils

xUtils 包括了非常多有用的android工具,xUtils 源於Afinal框架,對Afinal進行了大量重構,使得xUtils支持大文件上傳,更全面的http請求協議支持,擁有更加靈活的ORM,很多其它的事件註解支持且不受混淆影響.


xUitls最低兼容android 2.2 (api level 8)


xUtils下載和引入類庫


下載地址:https://github.com/wyouflf/xUtils
解壓包並將xUtils-*.jar拷貝到項目的libs下

為什麽要使用Xutils?


在aFinal基礎上進行重構和擴展的框架。相比aFinal有非常大的改善,
基於網路的應用,僅僅要處理得當,能讓大家徹底的擺脫各種工具類和反復代碼的困擾

xUtils實現的技術(重點)


Java反射(Reflect)技術

作用

  1. 動態獲取在當前Java虛擬機中的類、接口或者對象信息
  2. 解除兩個類之間的耦合性,即在未得到依賴類的情況下。自身應用能夠通過編譯
  3. 動態依賴註入(即須要某一類對象時動態生成類實例,並設置到被依賴的類中),降低編譯時的內存開銷
一句話:在執行時通過類名(一般聲明在了註解上)動態載入一個類。

獲取Class對象的三種方式

java中,一切皆對象。也就是說。基本類型int float 等也會在jvm的內存池像其它類型一樣中生成
一個Class對象。而數組等組合型數據類型也是會生成一個Class對象的。並且更令人吃驚的是。java中數組的本來面目事實上就是某個類。吃驚中的吃驚是。含有同樣元素的同樣維數的數組還會共同享用同一個Class對象!事實上依據我的臆想,數組的length性質應該就保存在這個Class對象裏面
1、使用Class類的靜態方法: Class.forName(String name) 2、類的語法:T.class,代表了與其匹配的Class對象 3、使用類的實例化的getClass方法: obj.getClass()

java.lang.Class類

獲取類的構造器java.lang.reflect.Constructor
獲取類的成員變量java.lang.reflect.Field

public Field[] getFields() 獲取全部的public成員變量 public Field getField(String name) 獲取隨意public成員變量
public Field[] getDeclaredFields() 獲取全部的成員變量 public Field getDeclaredField(String name) 獲取隨意指定名字的成員變量 public void setAccessible(boolean flag) 設置私有屬性是否可訪問 Field 重要方法set(Object obj, Object value) 字段設置為指定的新值。

獲取類的方法java.lang.reflect.Method

public Method[] getMethods() 獲取全部的共同擁有方法的集合 public Method getMethod(String name,Class<?

>... parameterTypes) 獲取指定公有方法

public Method[] getDeclaredMethods() 獲取全部的方法 public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 獲取隨意指定方法 Method重要方法invoke(Object obj ,Object…parmasType) 運行對象的方法,第一個參數為類實例對象,第二個參數:對象方法的參數

Class類的實例化方法 newInstance()
獲取類的全名:getName()
獲取類的簡稱:getSimpleName()
獲取類的包名:getPackage()






Java註解(Annotaion)技術

作用

註解相當於一種標記。程序中加了註解之即程序就有了標記,在其它程序中能夠用反射來了解你的類及各種元素上的標記。一般有什麽標記,就去幹對應的事。標記能夠加在包。類。字段,方法,方法的參數以及局部變量上。 一句話:註解是代碼的描寫敘述。

經常使用的3個註解

@Override 重寫父類或實現接口中的方法 @Deprecated 類或其成員已過時 @SuppressWarnings 排除相關警告

註解的聲明

[email protected],並聲明元註解(註解的註解,用於標識註解的生命周期、使用位置等)

4種元註解

@Retention元註解
表示須要在什麽級別保存該凝視信息(生命周期)
RetentionPolicy.SOURCE: 停留在java源文件,編譯器被丟掉
RetentionPolicy.CLASS:停留在class文件裏。但會被VM丟棄(默認)
RetentionPolicy.RUNTIME:內存中的字節碼。VM將在執行時也保留註解,因此能夠通過反射機制讀取註解的信息
@Target元註解
默認值為不論什麽元素,表示該註解用於什麽地方(類、方法、變量等)
ElementType.PACKAGE: 包聲明
ElementType.TYPE: 類、接口(包含註解類型)或enum聲明
ElementType.CONSTRUCTOR: 構造器聲明
ElementType.FIELD: 成員變量、對象、屬性(包含enum實例)
ElementType.METHOD: 方法聲明
ElementType.PARAMETER: 參數聲明
ElementType.LOCAL_VARIABLE: 局部變量聲明
@Documented :將註解包括在JavaDoc中
@Inheried :同意子類繼承父類中的註解

實例1: 註入姓名

第一步: File->New->Annotation,給定註解名(如Name) 第二步:聲明元註解,[email protected]@Target 第三步:聲明註解的屬性及默認值 第四步:使用註解 第五步: 解析註解
<span style="font-size:14px;">@Name 註解的定義。見com.qftrain.annotation.Name.java文件裏代碼:
--------------------------------------------------------------------------------

package com.qftrain.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)  //執行時
@Target(ElementType.FIELD)  //用於類中的屬性字段
public @interface Name {   
	
	//聲明註解的屬性
	String value() default "disen";
	
}     
--------------------------------------------------------------------------------

[email protected],見com.qftrain.test.T1.java文件裏代碼:
--------------------------------------------------------------------------------
package com.qftrain.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class T1 {

	@Name("你好!") //使用註解,向name屬性字段中註入內容
	public String name;
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		T1 t1=new T1();
		
		//解析T1類中的註解
		parseAnnotation(t1); 
	
		System.out.println(t1.name);
	}


	private static void parseAnnotation(T1 t1) {
		try {
			//獲取類中的相關屬性成員
			Field f= t1.getClass().getField("name");
			f.setAccessible(true); //設置屬性成員可訪問
			
			//TODO 獲取屬性成員的註解
			Annotation[] as= f.getDeclaredAnnotations();
			if(as!=null && as.length>0){
				Annotation a=as[0]; //假設註解存在。獲取第一個註解
				
				System.out.println(a.annotationType()); //獲取註解的類型
				
				String aName=a.annotationType().getName();
				if(aName.equals(Name.class.getName())){
					Name n=(Name)a; //假設註解是Name,則強轉
					
					f.set(t1, n.value());
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}</span>


實例2: 高速查找UI

第一步: [email protected] 第二步:[email protected] 第三步:創建BaseActivity,重寫onStart()[email protected] 第四步:應用註解查找UI
<span style="font-size:14px;">(一)[email protected],見com.qftrain.annotation.UI.java文件裏的代碼:
------------------------------------------------------------------------
package com.qftrain.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface UI {
	int id(); //View 的id
	String click() default "click"; 
}

------------------------------------------------------------------------


(二)[email protected]ler.java文件裏的代碼:
------------------------------------------------------------------------------------------
package com.qftrain.annotation;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;

public class UiHandler {

	// 處理Activity類中成員的註解
	public static void handleAnnotation(final Activity activity) {

		// 獲取類中全部成員
		Field[] fields = activity.getClass().getDeclaredFields();
		for (Field f : fields) {

			Log.i("anno", "field-" + f.getName());

			// 開啟類成員屬性的訪問性
			f.setAccessible(true);

			//獲取屬性字段的UI註解
			final UI ui = f.getAnnotation(UI.class); 

			if (ui != null) { //假設當前字段上包括UI註解

				Log.i("anno", "--" + ui.id());
				Log.i("anno", "--" + ui.click());
				try {

					//概據註入的id,查找Activity中View控件
					View view = activity.findViewById(ui.id());
					
					f.set(activity, view); // 設置View的實例
					
					// 查找Activity中的處理點擊事件的方法
					final Method method = activity.getClass()
							.getDeclaredMethod(ui.click(), View.class);

							
					// 推斷View是否註入了點擊事件
					if (!(ui.click().equals("click"))) {
						
						//設置點擊事件
						view.setOnClickListener(new OnClickListener() {
							@Override
							public void onClick(View v) {
								try {

									if (method != null) {
										method.setAccessible(true); //設置方法可訪問
										method.invoke(activity, v);
									}

								} catch (Exception e) {
									e.printStackTrace();
								}
							}
						});

					}

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

}

------------------------------------------------------------------------------------------
(三)創建BaseActivity類,代碼例如以下:

package com.qftrain.ui01;

import android.app.Activity;

import com.qftrain.annotation.UiHandler;

public class BaseActivity extends Activity {

	@Override
	protected void onStart() {
		super.onStart();

		//解析當前類及其子類的註解
		UiHandler.handleAnnotation(this);
	}

}
------------------------------------------------------------------------------------------
(四)[email protected],代碼例如以下:

package com.qftrain.ui01;

import android.app.Activity;

import com.qftrain.annotation.UiHandler;

public class BaseActivity extends Activity {

	@Override
	protected void onStart() {
		super.onStart();

		//解析當前類及其子類的註解
		UiHandler.handleAnnotation(this);
	}

}
------------------------------------------------------------------------------------------
package com.qftrain.ui01;

import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.qftrain.annotation.UI;

public class MainActivity extends BaseActivity {

	@UI(id = R.id.tvId,click="hiClick") //註入View的id和點擊事件處理方法
	private TextView tv;

	@UI(id = R.id.prgId)
	private ProgressBar prg;

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

	//事件處理方法
	public void hiClick(View view){
		Toast.makeText(getApplicationContext(), "您擊了我", 0).show();
	}
	
	@Override
	protected void onStart() {
		super.onStart();

		// 在代碼中引用顏色資源
		tv.setTextColor(getResources().getColor(R.color.yellow));

		new Thread() {
			@Override
			public void run() {
				int p = 0;
				while (p <= 100) {
					prg.setProgress(p);
					prg.setSecondaryProgress(p + 5);
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					p += 2;
				}
			}
		}.start();
	}

}</span>

四大模塊

ViewUtils模塊

模塊介紹

android中的ioc(控制反轉)框架,全然註解方式就能夠進行UI綁定和事件綁定。 新的事件綁定方式,使用混淆工具混淆後仍可正常工作; 眼下支持經常使用的20種事件綁定。參見ViewCommonEventListener類和包com.lidroid.xutils.view.annotation.event

查找UI控件

@ViewInject(R.id.edittext)

通過View的id,查找View
----------------------------
public class MainActivity extends Activity{
@ViewInject(R.id.tv1Id)
private TextView tv1;
@ViewInject(R.id.btn1Id)
private Button btn;
}

註冊UI控件的事件

@OnClick(R.id.download_btn)

一定要保證方法的訪問修飾符為public
同一時候方法的參數要與Android原來的監聽方法參數一致。不僅參數類型,並且要保證參數的順序
為id為btn1Id的Button控件設置點擊事件處理方法
------------------------------------------------------
@OnClick(R.id.btn1Id)
public void aa(View v){
Toast.makeText(getApplicationContext(),"hello",0).show();
}
------
說明:
1) 方法的訪問範圍一般為public ,但假設為private也不會正常運行。由於通過反射機制獲取的方法是全部方法。
2) 方法無返回類型
3) 方法的參數必須是View類型的。

</span>

解析UI凝視

ViewUtils.inject(this);

<span style="font-size:14px;">(一)在Activity中註入
------------------
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ViewUtils.inject(this); //註入view和事件
    ...
}

(二)在Fragment中註入
------------------
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.bitmap_fragment, container, false); // 載入fragment布局
    ViewUtils.inject(this, view); //註入view和事件
    ...
}

(三)在BaseAdapter中註入
------------------
public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder vHolder=null;
		if(convertView==null){
			convertView=LayoutInflater.from(context).inflate(R.layout.item_jx, null);
			vHolder=new ViewHolder();
			
			ViewUtils.inject(vHolder, convertView);
			...
		}
		...
}

(四)在PreferenceFragment中註入
------------------
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ViewUtils.inject(this, getPreferenceScreen()); //註入view和事件
    ...
}



 ViewUtils.inject()的重載方法
------------------
// inject(View view);
// inject(Activity activity)
// inject(PreferenceActivity preferenceActivity)
// inject(Object handler, View view)
// inject(Object handler, Activity activity)
// inject(Object handler, PreferenceGroup preferenceGroup)
// inject(Object handler, PreferenceActivity preferenceActivity)</span>

BitmapUtils模塊

模塊介紹

載入bitmap的時候無需考慮bitmap載入過程中出現的oom和android容器高速滑動時候出現的圖片錯位等現象
支持載入網絡圖片和本地圖片
內存管理使用lru算法,更好的管理bitmap內存
可配置線程載入線程數量,緩存大小,緩存路徑,載入顯示動畫等.

基本使用

實例化BitmapUtils

BitmapUtils bUtils=new BitmapUtils(getApplicationContext(),"/mnt/sdcard/");
bUtils.configThreadPoolSize(5); //配置線程池大小
bUtils.configDiskCacheEnabled(true); //啟用擴展存儲緩存


載入網絡圖片

bUtils.display(imageView, "http://www.baidu.com/logo.png")

載入本地圖片

bitmapUtils.display(imageView, "/sdcard/a.jpg")

載入assets中的圖片:載入本地圖片

bitmapUtils.display(imageView, "assets/a.jpg")

暫停載入監聽

在使用ListView顯示圖片時,能夠通過PauseOnScrollListener控制滑動和高速滑動過程中時暫停載入圖片
<span style="font-size:18px;">//僅處理與圖片相關的事件,第二個參數:滾動時是否暫停,第三個參數:高速滑動時是否暫停
listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, false, true));
//同一時候處理ListView.OnScrollListener事件
listView.setOnScrollListener(new PauseOnScrollListener(bitmapUtils, false, true, customListener));</span>

註意

BitmapLoadCallBack<T extends View>:圖片載入監聽器
onLoadCompleted:載入完畢了,可再次加入動畫顯示
onLoading:顯示載入圖片的進度
onLoadFailed:載入失敗的 處理

了解config打頭的方法

BitmapGlobalConfig配置

線程載入線程數量
bUtils.configThreadPoolSize(5); //配置線程池大小

配置緩存
路徑:/data/data/{package}/cache/xx
bUtils.configMemoryCacheEnabled(true)
bUtils.configDefaultCacheExpiry(100*1024); //100k
載入顯示動畫
bUtils.configDefaultImageLoadAnimation(Animation)

BitmapDisplayConfig配置

圖片寬高
bUtils.configDefaultBitmapMaxSize(int w,int h)
bUtils.configDefaultBitmapMaxSize(BitmapSize bs)
new BitmapSize(int w,int h) 指定寬和高
BitmapCommonUtils.getScreenSize(context) 根據屏幕尺寸
默認顯示圖片
bUtils.configDefaultLoadingImage(int resId)
bUtils.configDefaultLoadingImage(Bitmap b)
bUtils.configDefaultLoadingImage(Drawable d)
下載失敗圖片
bUtils.configDefaultLoadFailedImage(int resId)
bUtils.configDefaultLoadFailedImage(Bitmap b)
bUtils.configDefaultLoadFailedImage(Drawable d)
圖片保存質量
bUtils.configDefaultBitmapConfig(Bitmap.Config.RGB_565);
圖片載入動畫
bUtils.configDefaultImageLoadAnimation(Animation)
<span style="font-size:14px;">  //實例化圖片顯示的配置
			BitmapDisplayConfig bdConfig=new BitmapDisplayConfig();

			//設置顯示圖片特性
			bdConfig.setBitmapConfig(Bitmap.Config.ARGB_4444);
			bdConfig.setBitmapMaxSize(BitmapCommonUtils.getScreenSize(context)); //圖片的最大尺寸
			bdConfig.setLoadingDrawable(context.getResources().getDrawable(R.drawable.ic_default)); //載入時顯示的圖片
			bdConfig.setLoadFailedDrawable(context.getResources().getDrawable(R.drawable.ic_default)); //載入失敗時顯示的圖片
			bdConfig.setAutoRotation(true); //自己主動旋轉
			bdConfig.setShowOriginal(false); //不顯示源圖片
			bdConfig.setAnimation(AnimationUtils.loadAnimation(context, R.anim.slide_in_from_top)); //顯示圖片運行的動畫
			
			bUtils.configDefaultDisplayConfig(bdConfig); //將顯示圖片的配置設置到圖片工具類中</span>


HttpUtils模塊

模塊介紹

支持同步,異步方式的請求;
支持大文件上傳,上傳大文件不會oom;
支持GET,POST,PUT,MOVE。COPY,DELETE。HEAD。OPTIONS。TRACE。CONNECT請求;
下載支持301/302重定向,支持設置是否依據Content-Disposition重命名下載的文件;
返回文本內容的請求(默認僅僅啟用了GET請求)支持緩存,可設置默認過期時間和針對當前請求的過期時間。

普通get方法

<span style="font-size:18px;">HttpUtils http = new HttpUtils();
http.send(HttpRequest.HttpMethod.GET,
    "http://www.lidroid.com",
    new RequestCallBack<String>(){
        @Override
        public void onLoading(long total, long current, boolean isUploading) {
            testTextView.setText(current + "/" + total);
        }

        @Override
        public void onSuccess(ResponseInfo<String> responseInfo) {
            textView.setText(responseInfo.result);
        }

        @Override
        public void onStart() {
        }

        @Override
        public void onFailure(HttpException error, String msg) {
        }
});</span>

post方法


<span style="font-size:18px;">RequestParams params = new RequestParams();
params.addHeader("name", "value");
params.addQueryStringParameter("name", "value");

// 僅僅包括字符串參數時默認使用BodyParamsEntity。
// 相似於UrlEncodedFormEntity("application/x-www-form-urlencoded")。
params.addBodyParameter("name", "value");

// 增加文件參數後默認使用MultipartEntity("multipart/form-data"),
// 如需"multipart/related",xUtils中提供的MultipartEntity支持設置subType為"related"。
// 使用params.setBodyEntity(httpEntity)可設置很多其它類型的HttpEntity(如:
// MultipartEntity,BodyParamsEntity,FileUploadEntity,InputStreamUploadEntity,StringEntity)。

// 比如發送json參數:params.setBodyEntity(new StringEntity(jsonStr,charset)); params.addBodyParameter("file", new File("path")); ... HttpUtils http = new HttpUtils(); http.send(HttpRequest.HttpMethod.POST, "uploadUrl....", params, new RequestCallBack<String>() { @Override public void onStart() { testTextView.setText("conn..."); } @Override public void onLoading(long total, long current, boolean isUploading) { if (isUploading) { testTextView.setText("upload: " + current + "/" + total); } else { testTextView.setText("reply: " + current + "/" + total); } } @Override public void onSuccess(ResponseInfo<String> responseInfo) { testTextView.setText("reply: " + responseInfo.result); } @Override public void onFailure(HttpException error, String msg) { testTextView.setText(error.getExceptionCode() + ":" + msg); } });</span>


下載文件

<span style="font-size:18px;">HttpUtils http = new HttpUtils();
HttpHandler handler = http.download(url,"/data/data/package/cache/abc.apk",
    true, // 假設目標文件存在,接著未完畢的部分繼續下載。

server不支持RANGE時將從新下載。 true, // 假設從請求返回信息中獲取到文件名稱。下載完畢後自己主動重命名。 new RequestCallBack<File>() { @Override public void onStart() { testTextView.setText("conn..."); } @Override public void onLoading(long total, long current, boolean isUploading) { testTextView.setText(current + "/" + total); } @Override public void onSuccess(ResponseInfo<File> responseInfo) { testTextView.setText("downloaded:" + responseInfo.result.getPath()); } @Override public void onFailure(HttpException error, String msg) { testTextView.setText(msg); } }); ... //調用cancel()方法停止下載 handler.cancel();</span>




DbUtils模塊

模塊介紹

android中的orm框架,一行代碼就能夠進行增刪改查。 支持事務。默認關閉; 可通過註解自己定義表名,列名,外鍵,唯一性約束,NOT NULL約束。CHECK約束等(須要混淆的時候請註解表名和列名)。 支持綁定外鍵。保存實體時外鍵關聯實體自己主動保存或更新。 自己主動載入外鍵關聯實體。支持延時載入; 支持鏈式表達查詢。更直觀的查詢語義,參考以下的介紹或sample中的樣例。

基本使用

DbUtils db = DbUtils.create(this);
User user = new User(); //這裏須要註意的是User對象必須有id屬性。或者有[email protected]
user.setName("xiaoming");
user.setAge("21");
db.save(user); // 使用saveBindingId保存實體時會為實體的id賦值
...
// 查找
Parent entity = db.findById(Parent.class, parent.getId());
List<Parent> list = db.findAll(Parent.class);//通過類型查找

Parent Parent = db.findFirst(Selector.from(Parent.class).where("name","=","test"));

// IS NULL
Parent Parent = db.findFirst(Selector.from(Parent.class).where("name","=", null));
// IS NOT NULL
Parent Parent = db.findFirst(Selector.from(Parent.class).where("name","!=", null));

// WHERE id<54 AND (age>20 OR age<30) ORDER BY id LIMIT pageSize OFFSET pageOffset
List<Parent> list = db.findAll(Selector.from(Parent.class)
                                   .where("id" ,"<", 54)
                                   .and(WhereBuilder.b("age", ">", 20).or("age", " < ", 30))
                                   .orderBy("id")
                                   .limit(pageSize)
                                   .offset(pageSize * pageIndex));

// op為"in"時,最後一個參數必須是數組或Iterable的實現類(比如List等)
Parent test = db.findFirst(Selector.from(Parent.class).where("id", "in", new int[]{1, 2, 3}));
// op為"between"時,最後一個參數必須是數組或Iterable的實現類(比如List等)
Parent test = db.findFirst(Selector.from(Parent.class).where("id", "between", new String[]{"1", "5"}));

DbModel dbModel = db.findDbModelAll(Selector.from(Parent.class).select("name"));//select("name")僅僅取出name列
List<DbModel> dbModels = db.findDbModelAll(Selector.from(Parent.class).groupBy("name").select("name", "count(name)"));
...

List<DbModel> dbModels = db.findDbModelAll(sql); // 自己定義sql查詢
db.execNonQuery(sql) // 運行自己定義sql
...


DbUtils和HttpUtils參考:http://blog.csdn.net/rain_butterfly/article/details/37812371

[android]Xutils具體介紹