xUtils是一個android使用工具框架,包含了如下幾大功能:
註解定義:提供了佈局,視圖和事件等註解,能夠簡化相關的Android代碼;
網絡請求:支持GET、PUT、DELETE和PUT等請求方式,封裝了異步Task,支持FIFO和FILO優先級線程池,提供了同步異步請求,支持https、cookie和硬盤緩存等;
圖片綁定:封裝了內存和硬盤緩存,優化了Bitmap加載過程,處理了ViewHolder產生的圖片錯亂問題,支持https等;
數據封裝:封裝了相關概念,直接將JavaBean映射成對應的表,封裝sql語句的select、where和insert等語句操作等;
具體的實現,大家可以到github(https://github.com/wyouflf/xUtils3)上下載相關源碼進行學習。下面我們就xUtils3的基本使用,結合一個圖片列表的Demo跟大家進行介紹。該項目的源碼使用了MVP和Https相關知識,如果有看不明白,請閱讀Android實踐《Https實現》和《MVC到MVP》相關博客進行了解;
二、xUtils3使用
1.首先看下我們項目結構,如下圖:
common:項目公共庫,包含了該項目公共類,如QBaseActivity.java,在這裏執行xUtils的Activity注入;
home:項目app,在這裏使用xUtils框架實現了一個簡單的列表功能,其中使用了註解、網絡請求(https)和圖片綁定等;
... ...
2.xUtils的接入
在build.gradle構建文件中添加xUtils框架的依賴;
common/build.gradle
apply plugin: 'com.android.library'
android {
... ...
}
dependencies {
... ...
compile 'com.alibaba:fastjson:1.1.54.android'
//聲明xutils依賴
compile 'org.xutils:xutils:3.3.38'
testCompile 'junit:junit:4.12'
}
在AndroidManifest.xml中添加相關權限;<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.qunar.home">
//聲明相關權限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application>
... ...
</application>
</manifest>
3.xUtils @ContentView @ViewInject和@Event註解的使用;在Application類中初始化xUtils框架;
home/src/main/com.qunar.home/QAppliction.java
public class QAplication extends Application{
@Override
public void onCreate() {
super.onCreate();
//初始化XUtils框架
x.Ext.init(this);
x.Ext.setDebug(BuildConfig.DEBUG); // 開啓debug會影響性能
}
}
將Activity或者Fragment注入到xUtils框架,這裏我們抽象出BaseActivity;common/src/main/com.qunar.common/QBaseActivity.java
public class QBaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注入activity,用戶處理Activity以內的所有註解
x.view().inject(this);
}
}
通過在繼承QBaseActivity的類中等地方,使用@ContentView設置Activity或者Fragment等佈局,@ViewInject查找視圖對象和@Event註冊點擊事件 ;home/src/main/com.qunar.home/render/view/RenderActivity.java
//代替setContentView()方法設置Activity的佈局
@ContentView(R.layout.activity_render)
public class RenderActivity extends QBaseActivity implements RenderContact.ViewQ {
//代替findById獲取視圖對象
@ViewInject(R.id.listview_render)
private ListView renderListView;
private RenderContact.PresenterQ renderPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
renderPresenter = new RenderPresenterQ(this);
renderPresenter.showRenderList(this);
}
@Override
public void setPresenter(RenderContact.PresenterQ presenter) {
renderPresenter = presenter;
}
@Override
public void initRenderListShow(RenderResultQ renderResult) {
RenderListAdapter renderListAdapter = new RenderListAdapter(this, renderResult.getRenderListItemList());
renderListView.setAdapter(renderListAdapter);
}
//通過@Event註解,註冊列表選項的點擊事件
@Event(value = R.id.listview_render, type = AdapterView.OnItemClickListener.class)
private void onImageItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this, "Title " + position + " is click", Toast.LENGTH_SHORT).show();
}
}
問題1:在使用@ContentView等註解時,Android Studio提示錯誤Attribute value must be constant分析1:檢查代碼是否爲Android的庫項目,該項目的R.java文件中的值不爲static final
處理1:在非Android的庫中使用註解;
4.xUtils網絡請求的使用;
在Presenter層,RenderPresenter層使用x.http().get()方法請求Render列表數據,創建RequestParams,並設置了https相關操作;
home/src/main/com.qunar.home/render/presenter/RenderPresenter.java
public class RenderPresenter implements RenderContact.PresenterQ {
private RenderContact.ViewQ renderView;
public RenderPresenter(RenderContact.ViewQ renderView) {
this.renderView = renderView;
}
@Override
public void start() {
}
@Override
public void showRenderList(Context context) {
//Presenter層,請求Render列表數據
RequestParams renderParams = new RequestParams(QConfig.SERVER_URL + "RenderServlet");
//採用https請求方法,獲取sslContext,設置socketFactory
renderParams.setSslSocketFactory(HttpsTools.getSSLContext(context).getSocketFactory());
x.http().post(renderParams, new Callback.CommonCallback<QRenderResult>() {
@Override
public void onSuccess(RenderResultQ result) {
//調用View接口層方法,顯示Render列表數據
renderView.initRenderListShow(result);
}
@Override
public void onError(Throwable ex, boolean isOnCallback) {
Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
}
@Override
public void onCancelled(CancelledException cex) {
Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
}
@Override
public void onFinished() {
}
});
}
}
創建請求結果對象,使用@HttpResponse註解設置返回結果解析器;//設置返回結果的Json解析器
@HttpResponse(parser = JsonResponseParser.class)
public class RenderResult extends QBaseResult {
private List<RenderListItem> renderListItemList;
public RenderResult(){}
public List<RenderListItem> getRenderListItemList() {
return renderListItemList;
}
public void setRenderListItemList(List<RenderListItem> renderListItemList) {
this.renderListItemList = renderListItemList;
}
public class RenderListItem implements Serializable{
private String imageUrl;
private String itemTitle;
private String itemDescription;
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getItemTitle() {
return itemTitle;
}
public void setItemTitle(String itemTitle) {
this.itemTitle = itemTitle;
}
public String getItemDescription() {
return itemDescription;
}
public void setItemDescription(String itemDescription) {
this.itemDescription = itemDescription;
}
}
}
創建Json結果解析器實現ResponseParser,覆蓋parse()方法,解析返回的json字符串;public class JsonResponseParser implements ResponseParser {
@Override
public void checkResponse(UriRequest request) throws Throwable {
}
@Override
public Object parse(Type resultType, Class<?> resultClass, String result) throws Throwable {
//使用fastJson解析返回結果,這裏應該判斷返回類型分別解析parseObject或者parseArray
return JSON.parseObject(result, resultClass);
}
}
5.xUtils綁定圖片的使用;在Render列表的適配器中,使用x.image().bind()方法將ImageView加載相關的圖片url,由於圖片是https請求,ImageOptions進行相關操作;
home/src/main/com.qunar.home/render/view/ RenderListAdapter.java
public class RenderListAdapter extends BaseAdapter {
private List<RenderResult.RenderListItem> renderListItems;
private final LayoutInflater layoutInflater;
private ImageOptions imageOptions;
public RenderListAdapter(final Context context, List<RenderResult.RenderListItem> renderListItems) {
this.renderListItems = renderListItems;
this.layoutInflater = LayoutInflater.from(context);
//初始化加載圖片參數,詳情可以查看Android實踐《高效加載Bitmap》章節,https操作
this.imageOptions = new ImageOptions.Builder().setSize(DensityUtil.dip2px(120), DensityUtil.dip2px(120)).setRadius(DensityUtil.dip2px(5)).setCrop(true).setImageScaleType(ImageView.ScaleType.CENTER_CROP).setLoadingDrawableId(R.mipmap.ic_launcher).setFailureDrawableId(R.mipmap.ic_launcher).setParamsBuilder(new ImageOptions.ParamsBuilder() {
@Override
public RequestParams buildParams(RequestParams params, ImageOptions options) {
//設置https SSLContext,SslSocketFactory等
params.setSslSocketFactory(HttpsTools.getSSLContext(context).getSocketFactory());
return params;
}
}).build();
}
@Override
public int getCount() {
return renderListItems.size();
}
@Override
public Object getItem(int position) {
return renderListItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ItemHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.listitem_render, parent, false);
holder = new ItemHolder();
x.view().inject(holder, convertView);
convertView.setTag(holder);
} else {
holder = (ItemHolder) convertView.getTag();
}
RenderResultQ.RenderListItem renderListItem = renderListItems.get(position);
//使用x.image().bind()方法加載圖片
x.image().bind(holder.imageView, renderListItem.getImageUrl(), imageOptions);
holder.title.setText(renderListItem.getItemTitle());
holder.description.setText(renderListItem.getItemDescription());
return convertView;
}
private class ItemHolder {
@ViewInject(R.id.listitem_render_imageview)
private ImageView imageView;
@ViewInject(R.id.listitem_render_title)
private TextView title;
@ViewInject(R.id.listitem_render_description)
private TextView description;
}
}
6.xUitls數據庫訪問的使用;數據庫訪問,可查看官網,該Demo並沒有演示;
7.其它實現代碼,就不一一列舉了,請自行下載源碼進行了解。項目運行效果如下:
問題2:實現RenderServlet.java模擬接口時報錯:HTTP Status 405 - HTTP method GET is not supported by this URL
處理2:在Servlet中重寫的doGet方法不要調用super;
三、代碼庫
QProject:https://github.com/Pengchengxiang/QProject 分支:feature/xutils3