網站:https://github.com/wyouflf/xUtils3 (里面有aar文件的下載地址)
- xUtils3變化較多所以建立了新的項目不在舊版(github.com/wyouflf/xUtils)上繼續維護, 相對於舊版本:
- HTTP實現替換HttpClient為UrlConnection, 自動解析回調泛型, 更安全的斷點續傳策略.
- 支持標准的Cookie策略, 區分domain, path...
- 事件注解去除不常用的功能, 提高性能.
- 數據庫api簡化提高性能, 達到和greenDao一致的性能.
- 圖片綁定支持gif(受系統兼容性影響, 部分gif文件只能靜態顯示), webp; 支持圓角, 圓形, 方形等裁剪, 支持自動旋轉..
也正是因為安卓6.0不能使用HttpClient了,所以xUtils2就有影響了,因為內部很多都是使用的HttpClient
將xUtils3.0導入項目:
使用Gradle構建時添加一下依賴即可:
compile 'org.xutils:xutils:3.3.36'
使用Eclipse構建時操作步驟如下: (aar文件下載地址: http://dl.bintray.com/wyouflf/maven/org/xutils/xutils/ )
- 下載aar文件並使用然后用zip解壓, 取出jar包和so文件. aar文件在上面給的github網站里有說到
- 將xutils.jar 以及armeabi目錄下的.so文件添加到工程的libs中即可。
所需權限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
在application的onCreate中初始化: 切記在清單文件加name屬性 android:name=".MyApplication"
public class MyApplication extends Application { @Override publicvoidonCreate() { super.onCreate(); x.Ext.init(this);//Xutils初始化,這一步之后, 我們就可以在任何地方使用x.app()來獲取Application的實例了. x.Ext.setDebug(true); // 是否輸出debug日志 } }
注解的使用可以參考: http://blog.csdn.net/qq_25508039/article/details/50902620
利用XUtils3對數據庫的操作,以及注解的使用,與Xutils2有很大的區別:
import org.xutils.db.annotation.Column; import org.xutils.db.annotation.Table; /** * 數據庫表的實體類 */ @Table(name = "student") //確定表名 public class Student { //必須要有無參構造,否則創建表不成功 public Student() { } @Column(name = "_id", isId = true, autoGen = true)//isId為true,代表為主鍵,autoGen為true代表自增 public int _id; @Column(name = "name")//設置為列名 public String name;// 姓名 @Column(name = "age") public int age;// 年齡 @Column(name = "sex") public String sex;// 性別 public int get_id() { return _id; } public void set_id(int _id) { this._id = _id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
具體的操作:
import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import org.xutils.DbManager; import org.xutils.db.sqlite.SqlInfo; import org.xutils.db.sqlite.WhereBuilder; import org.xutils.db.table.DbModel; import org.xutils.db.table.TableEntity; import org.xutils.ex.DbException; import org.xutils.view.annotation.ContentView; import org.xutils.view.annotation.Event; import org.xutils.x; import java.util.ArrayList; import java.util.List; /** * XUtils3對數據庫的操作 */ @ContentView(R.layout.activity_main) //加載的xml文件 public class MainActivity extends AppCompatActivity { /** * 數據庫的配置信息對象 */ private DbManager.DaoConfig daoConfig; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); x.view().inject(this);//綁定注解 //初始化數據庫配置信息 initDaoConfig(); } @Event(value = {R.id.add ,R.id.query,R.id.updata,R.id.delete}) private void btnOnClick(View view){ //必須是private單擊事件才有效 switch (view.getId()){ case R.id.add: addData(); break; case R.id.query: onQuertyData(); break; case R.id.updata: onUPdataData(); break; case R.id.delete: deleteData(); break; } } /** * 增加數據,插入數據庫操作的時候會判斷是否存在這張表,如果不存在就會去創建,所以不需要手動去創建表了 */ public void addData(){ try { //根據配置信息獲取操作數據的db對象 DbManager db = x.getDb(daoConfig); List<Student> list = new ArrayList<Student>(); for (int i = 0; i < 10; i++) { Student stu = new Student(); stu.setAge(10+i); stu.setName("學生"+i); stu.setSex(i % 2 == 0? "男":"女"); list.add(stu); //db.save(stu);//插入一條數據 } db.save(list);//保存實體類或實體類的List到數據庫 //db.replace(list);保存或更新實體類或實體類的List到數據庫, 根據id和其他唯一索引判斷數據是否存在 //db.saveOrUpdate(list);保存或更新實體類或實體類的List到數據庫, 根據id對應的數據是否存在. //db.saveBindingId(list);保存實體類或實體類的List到數據庫,如果該類型的id是自動生成的, 則保存完后會給id賦值. /** * 1.如果在你建表的時候你的主鍵設置成自增長,那么你在插入數據的時候直接調replace方法就可以了, * 但是saveOrUpdate只能達到插入的效果,達不到更新原有數據的效果. * 2.如果在你建表的時候你的主鍵設置成不是自增長,replace方法當然可以插入,saveOrUpdate方法既可以插入也可以達到更新的效果 */ } catch (DbException e) { e.printStackTrace(); } } /** * 查詢數據 */ public void onQuertyData(){ try { DbManager db = x.getDb(daoConfig); Student student = db.findById(Student.class, 2);//根據主鍵來查找student表里的數據 Student first = db.findFirst(Student.class);//返回當前表的第一條數據 Log.i("tag", "第一條數據:"+first); //查詢所有數據 List<Student> all = db.findAll(Student.class); Log.i("tag", "所有數據:"+all.toString()); //按條件查找,查詢年齡大於15的 List<DbModel> dbModelAll = db.findDbModelAll(new SqlInfo("select * from student where age > 15")); for (int i = 0; i < dbModelAll.size() ; i++) { String name = dbModelAll.get(i).getString("name"); String age = dbModelAll.get(i).getString("age"); String sex = dbModelAll.get(i).getString("sex"); Log.i("tag", "查詢的數據: name="+name+",age="+age+",sex="+sex); } //第二種條件查找 List<Student> all1 = db.selector(Student.class).where("age", ">", 14).and("age", "<", 16).findAll(); //第三種 List<Student> all2 = db.selector(Student.class).expr("age>14 and age<17").findAll(); Log.i("tag", "第二種:"+all1.toString()); } catch (DbException e) { e.printStackTrace(); } } /** * 更新數據 */ public void onUPdataData(){ try { DbManager db = x.getDb(daoConfig); //先找到要更新的數據,再設置值,然后更新,當然你也可以使用上面查詢數據的方式 Student stu3 = db.findById(Student.class, 3);//找到主鍵為3的值 stu3.setAge(50); db.update(stu3,"age");//更新stu3列名為age的數據 } catch (DbException e) { e.printStackTrace(); } } /** * 刪除數據 */ public void deleteData(){ try { //第一種,根據主鍵來刪除 DbManager db = x.getDb(daoConfig); db.deleteById(Student.class,5);//刪除主鍵為5的值 //第二種方法,找到符合條件的第一條數據 .findAll()就是找所有符合條件的了 Student student = db.selector(Student.class).where("name", "=", "學生11").findFirst(); db.delete(student);//先找到,再刪除 ,需要判斷為不為空 //第三種,刪除那name=學生9 且 sex=女 的數據 db.delete(Student.class, WhereBuilder.b("name","=" ,"學生9").and("sex","=","女")); //第四種,刪除所有數據,但是表還在 db.delete(Student.class); //db.dropTable(Student.class);刪除表 //db.dropDb();刪除數據庫 } catch (DbException e) { e.printStackTrace(); } } /** * 初始化獲取數據庫的配置信息 */ public void initDaoConfig(){ daoConfig = new DbManager.DaoConfig() .setDbName("my.db") //設置數據庫名稱 .setDbVersion(1) //設置數據庫版本 .setDbDir(getCacheDir().getAbsoluteFile()) //設置數據庫保存的路徑 .setAllowTransaction(true) //設置允許開啟事務 .setDbUpgradeListener(new DbManager.DbUpgradeListener() { @Override public void onUpgrade(DbManager db, int oldVersion, int newVersion) { //db.addColumn("表名","需要增加的列名");數據庫更新監聽 } }) .setDbOpenListener(new DbManager.DbOpenListener() { @Override public void onDbOpened(DbManager db) { //開啟WAL.對寫入加速提示很大 db.getDatabase().enableWriteAheadLogging(); } }) .setTableCreateListener(new DbManager.TableCreateListener() { @Override public void onTableCreated(DbManager db, TableEntity<?> table) { Log.i("tag", "onTableCreated: 創建了表:"+table.getName()); } }); } }
Xutils3的Get與Post請求:
/** * Get請求,可以直接在主線程中調用該方法 */ public void xUtils3Get(String url){ //設置網絡請求的參數 RequestParams params = new RequestParams(url); //使用的普通回調 Callback.Cancelable cancelable = x.http().get(params, new Callback.CommonCallback<String>() { @Override public void onSuccess(String result) { Log.i("tag", "請求成功: "+result); } @Override public void onError(Throwable ex, boolean isOnCallback) { Log.i("tag", "請求異常"); } @Override public void onCancelled(CancelledException cex) { Log.i("tag", "取消請求的回調方法"); } @Override public void onFinished() { Log.i("tag", "請求完成,並不一定是請求成功,斷開了連接就會執行該方法"); } }); //cancelable.cancel();取消請求 } /** * Post請求,可以直接在主線程中調用該方法 */ public void xUtils3Post(String url){ //設置網絡請求的參數,以及post的字段 RequestParams params = new RequestParams("http://mrobot.pcauto.com.cn/v2/cms/channels/1?"); //post提交的字段:pageNo=1&pageSize=20&serialIds=2143,3404&v=4.0.0 params.addBodyParameter("pageNo","1"); params.addBodyParameter("pageSize","20"); params.addBodyParameter("serialIds","2143,3404"); params.addBodyParameter("v","4.0.0"); //使用的普通回調 Callback.Cancelable cancelable = x.http().post(params, new Callback.CommonCallback<String>() { @Override public void onSuccess(String result) { Log.i("tag", "請求成功: "+result); } @Override public void onError(Throwable ex, boolean isOnCallback) { Log.i("tag", "請求異常"); } @Override public void onCancelled(CancelledException cex) { Log.i("tag", "取消請求的回調方法"); } @Override public void onFinished() { Log.i("tag", "請求完成,並不一定是請求成功,斷開了連接就會執行該方法"); } }); //cancelable.cancel();取消請求 }
使用Xutils3實現斷點下載:
import android.app.ProgressDialog; import android.content.DialogInterface; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import org.xutils.common.Callback; import org.xutils.common.task.PriorityExecutor; import org.xutils.http.RequestParams; import org.xutils.view.annotation.ContentView; import org.xutils.view.annotation.Event; import org.xutils.x; import java.io.File; /** * XUtils3實現斷點下載 */ @ContentView(R.layout.activity_main) //加載的xml文件 public class MainActivity extends AppCompatActivity { /** * 可取消的任務 */ private Callback.Cancelable cancelable; /** * 進度條對話框 */ private ProgressDialog progressDialog; private String pathApk = "http://down.72g.com/upload/app/201407/201407150923238621.apk"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); x.view().inject(this);//綁定注解 initProgressDialog(); } @Event(R.id.download) private void btnOnClick(View view){ //設置請求參數 RequestParams params = new RequestParams(pathApk); params.setAutoResume(true);//設置是否在下載是自動斷點續傳 params.setAutoRename(false);//設置是否根據頭信息自動命名文件 params.setSaveFilePath("/sdcard/xutils/xUtils_1.avi"); params.setExecutor(new PriorityExecutor(2, true));//自定義線程池,有效的值范圍[1, 3], 設置為3時, 可能阻塞圖片加載. params.setCancelFast(true);//是否可以被立即停止. //下面的回調都是在主線程中運行的,這里設置的帶進度的回調 cancelable = x.http().get(params, new Callback.ProgressCallback<File>() { @Override public void onCancelled(CancelledException arg0) { Log.i("tag", "取消"+Thread.currentThread().getName()); } @Override public void onError(Throwable arg0, boolean arg1) { Log.i("tag", "onError: 失敗"+Thread.currentThread().getName()); progressDialog.dismiss(); } @Override public void onFinished() { Log.i("tag", "完成,每次取消下載也會執行該方法"+Thread.currentThread().getName()); progressDialog.dismiss(); } @Override public void onSuccess(File arg0) { Log.i("tag", "下載成功的時候執行"+Thread.currentThread().getName()); } @Override public void onLoading(long total, long current, boolean isDownloading) { if (isDownloading) { progressDialog.setProgress((int) (current*100/total)); Log.i("tag", "下載中,會不斷的進行回調:"+Thread.currentThread().getName()); } } @Override public void onStarted() { Log.i("tag", "開始下載的時候執行"+Thread.currentThread().getName()); progressDialog.show(); } @Override public void onWaiting() { Log.i("tag", "等待,在onStarted方法之前執行"+Thread.currentThread().getName()); } }); } /*初始化對話框*/ private void initProgressDialog() { //創建進度條對話框 progressDialog = new ProgressDialog(this); //設置標題 progressDialog.setTitle("下載文件"); //設置信息 progressDialog.setMessage("玩命下載中..."); //設置顯示的格式 progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //設置按鈕 progressDialog.setButton(ProgressDialog.BUTTON_NEGATIVE, "暫停",new DialogInterface.OnClickListener(){ @Override public void onClick(DialogInterface dialog, int which) { //點擊取消正在下載的操作 cancelable.cancel(); }}); } }
效果圖:
一些其他請求方式:
//使用緩存下載 @Event(R.id.btn) private void btnOnClick(View view){ //設置網絡請求的參數 RequestParams params = new RequestParams("http://m2.qiushibaike.com/article/list/latest?page=1"); params.setCacheMaxAge(1000 * 15);//設置緩存的時間 //使用帶緩存的回調 Callback.Cancelable cancelable = x.http().get(params, new Callback.CacheCallback<String>(){ @Override public void onSuccess(String result) { Log.i("tag", "請求成功: "+result); } @Override public void onError(Throwable ex, boolean isOnCallback) { } @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } @Override public boolean onCache(String result) { //在setCacheMaxAge設置范圍(上面設置的是15秒)內,如果再次調用GET請求, //返回true:緩存內容被返回,相信本地緩存,返回false:緩存內容被返回,不相信本地緩存,仍然會請求網絡 Log.i("tag","緩存的:"+result); return true; } }); //cancelable.cancel();取消請求 } /** * 上傳文件 */ private void upload(View v){ String path="/mnt/sdcard/Download/icon.jpg"; RequestParams params = new RequestParams("地址"); params.setMultipart(true); params.addBodyParameter("file",new File(path));//設置上傳的文件路徑 x.http().post(params, new Callback.CommonCallback<String>() { @Override public void onSuccess(String result) { } @Override public void onError(Throwable ex, boolean isOnCallback) { } @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } }); }
使用XUtils3緩存bitmap圖片:
//對圖片的操作 public void operationImg(String url){ //設置下載的圖片參數 ImageOptions.Builder builder = new ImageOptions.Builder(); builder.setFadeIn(true);//設置為淡入效果 //builder.setCircular(true);//設置圖片顯示為圓形 builder.setSquare(true);//設置圖片顯示為正方形 builder.setCrop(true);//如果ImageView的大小不是定義為wrap_content, 不要crop. builder.setSize(200,200);//設置圖片的大小 builder.setImageScaleType(ImageView.ScaleType.CENTER_CROP);//設置圖片的縮放模式 //builder.setFailureDrawableId();設置加載圖片失敗的圖片 //builder.setLoadingDrawableId();設置加載中的圖片 //builder.setPlaceholderScaleType(ImageView.ScaleType.MATRIX);加載中或錯誤圖片的ScaleType //builder.setIgnoreGif(true);設置為忽略Gif圖片 //builder.setParamsBuilder();設置參數,包括線程池,緩存文件名的設置,大小的設置,等等 builder.setRadius(50);//設置拐角的弧度(四個角的弧度) builder.setUseMemCache(false);//設置使用緩存(優先sd卡),默認為true ImageOptions options = builder.build(); //x.image().clearCacheFiles();清除磁盤緩存的文件夾 //x.image().clearMemCache();清除內部緩存 //加載本地圖片 //x.image().bind(imageView, new File("/sdcard/test.gif").toURI().toString(), options); //x.image().bind(imageView, "/sdcard/test.gif", options); //x.image().bind(imageView, "file:///sdcard/test.gif", options); //加載網絡圖片 //x.image().bind(imageView,url); x.image().bind(imageView,url,options); /* x.image().bind(imageView, url, options, new Callback.CacheCallback<Drawable>() { @Override public boolean onCache(Drawable result) { return false; } @Override public void onSuccess(Drawable result) { } @Override public void onError(Throwable ex, boolean isOnCallback) { } @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } });*/ }
關於緩存的一些參數:
/* // 擴展參數 關於緩存的信息在 :ImageLoader類中 private final static String DISK_CACHE_DIR_NAME = "xUtils_img"; //SD卡的緩存名 private final static Executor EXECUTOR = new PriorityExecutor(10, false);//默認線程數 private final static int MEM_CACHE_MIN_SIZE = 1024 * 1024 * 4; // 4M 內存緩存最小為4兆 可以自己設置 private static final int LIMIT_COUNT = 5000; // 限制最多5000條數據 private static final long LIMIT_SIZE = 1024L * 1024L * 100L; // 限制最多100M文件
private Proxy proxy; // 代理 private boolean useCookie = true; // 是否在請求過程中啟用cookie private String cacheDirName; // 緩存文件夾名稱 private long cacheSize; // 緩存文件夾大小 private long cacheMaxAge; // 默認緩存存活時間, 單位:毫秒.(如果服務沒有返回有效的max-age或Expires) private Executor executor; // 自定義線程池 private Priority priority = Priority.DEFAULT; // 請求優先級 private int connectTimeout = 1000 * 15; // 連接超時時間 private boolean autoResume = true; // 是否在下載是自動斷點續傳 private boolean autoRename = false; // 是否根據頭信息自動命名文件 private int maxRetryCount = 2; // 最大請求錯誤重試次數 private String saveFilePath; // 下載文件時文件保存的路徑和文件名 private boolean cancelFast = false; // 是否可以被立即停止, true: 為請求創建新的線程, 取消時請求線程被立即中斷. private int loadingUpdateMaxTimeSpan = 300; // 進度刷新最大間隔時間(ms) private HttpRetryHandler httpRetryHandler; // 自定義HttpRetryHandler private RedirectHandler redirectHandler; // 自定義重定向接口, 默認系統自動重定向. private RequestTracker requestTracker; // 自定義日志記錄接口.*/ //設置參數的使用 builder.setParamsBuilder(new ImageOptions.ParamsBuilder(){ @Override public RequestParams buildParams(RequestParams params, ImageOptions options) { params.setCacheDirName("mySDCache");//設置sd卡上的緩存文件名,默認為xUtils_img long cacheSize = params.getCacheSize(); Log.i("tag", "緩存大小:"+cacheSize/1024); return params; } }); builder.setUseMemCache(true);//設置使用緩存(優先sd卡),默認為true options = builder.build();