标签:complete 目的 hba other access 检查 ram 填充 man
在寻常的开发中常常会有非常多列表页面。每做一个列表页就须要创建这个布局文件那个Adapter适配器文件等等一大堆与之相关的附属的不必要的冗余文件。
假设版本号更新迭代比較频繁,如此以往,就会使项目project变得无比庞大臃肿。
假设看过这篇文章或者在使用过这样的方式之后呢,全部的工作都能够被压缩成仅仅有两个文件,一个JAVA文件一个XML布局文件。
并且代码还少少的。
咱们来看看实际情况:
寻常的一个列表页面的生成须要下面文件:
/**
* 演示样例代码,将关键的部分放在fragment中。不管是viewpager还是Activity。还是其他容器,都能够将fragment嵌入当中显示
*
* @author Sahadev
*
*/
public class ExampleFragment extends SuperAbstListFragment<ExampleBean> {
public static AbstListFragment getInstance(String requestUrl) {
AbstListFragment fragment = new ExampleFragment();
Bundle bundle = new Bundle();
bundle.putString(AbstListFragment.URL, requestUrl);
fragment.setArguments(bundle);
return fragment;
}
@Override
public Type getInstanceType() {
// 返回须要实例化的对象类型
return new TypeToken<List<ExampleBean>>() {
}.getType();
}
/**
* 须要实例化的类,这里仅用一个属性做样例
*
* @author Work
*
*/
public static class ExampleBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 7624541082621792974L;
@SerializedName("title")
public String title;
}
//在这里完毕数据绑定就能够了,支持链式调用
@Override
public void setView(ViewHolder viewHolder, ExampleBean t) {
viewHolder.setText(R.id.title, t.title);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
}/**
* 基本类。提供一些经常使用的主要的方法属性供子类使用
*
* @author Sahadev
*
*/
public class BaseFragment extends Fragment {
/**
* 图片载入工具
*/
protected ImageLoader mImageLoader;
/**
* 等待对话框
*/
private LoadingDialog mLoadingDialog;
/**
* 布局填充器
*/
protected LayoutInflater mInflater;
/**
* context
*/
protected Activity mContext;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mContext = activity;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// 在此处初始化mImageLoader,mLoadingDialog等属性
mLoadingDialog = LoadingDialog.getInstance(mContext);
// imageLoader属性可在自己定义的Application中设置全局的单例。由自己定义Application暴露接口获取单例,比方
// mImageLoader = CustomApplication.getImageLoaderInstance();
}
/**
* 吐司
*
* @param message
*/
protected void toast(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
/**
* 显示等待对话框。显示默认文本
*/
protected void showLoadingDialog() {
if (mLoadingDialog != null) {
mLoadingDialog.show();
}
}
/**
* 显示等待对话框,显示传入的文本
*
* @param message
*/
public void showLoadingDialog(String message) {
if (mLoadingDialog != null) {
mLoadingDialog.setMessage(message);
mLoadingDialog.show();
}
}
/**
* 关闭等待对话框
*/
protected void dismissLoadingDialog() {
if (mLoadingDialog != null) {
mLoadingDialog.dismiss();
}
}
@Override
public void onDestroy() {
super.onDestroy();
dismissLoadingDialog();
}
}/**
* 含有ListView的Fragment
* 抽取公共的含有ListView的Fragment。此Fragment已经包含主要的下拉刷新,网络载入,分页载入等公共功能,仅仅须要关心实现 推荐使用
* {@link #SuperAbstListFragment}实例化子类方式參见{@link #ExampleFragment}
*
* @author Sahadev
*
*/
public abstract class AbstListFragment extends BaseFragment implements OnItemClickListener, OnClickListener,
Listener<JSONObject>, ErrorListener, OnRefreshListener2<ListView> {
protected PullToRefreshListView mListView;
protected ImageView emptyView;
private AnimationDrawable rocketAnimation;
private View rootView;
protected int page = 0;
public static final String URL = "ABST_LIST_FRAGMENT_URL";
public static final String NEED_REFRESH_BROADCAST_RECEIVER = "NEED_REFRESH_BROADCAST_RECEIVER";
/**
* 请求的链接地址
*/
protected String requestUrl;
/**
* 由子类实现。安全传參
*
* @param requestUrl
* @return
*/
public static AbstListFragment getInstance(String requestUrl) {
return null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (rootView == null) {
rootView = inflater.inflate(R.layout.activity_list_layout, container, false);
emptyView = (ImageView) rootView.findViewById(R.id.empty_view);
mListView = (PullToRefreshListView) rootView.findViewById(R.id.list);
mListView.setEmptyView(emptyView);
mListView.getRefreshableView().setLayoutTransition(new LayoutTransition());
mListView.setOnRefreshListener(this);
mListView.setOnItemClickListener(this);
mListView.getRefreshableView().setOnItemClickListener(this);
emptyView.setOnClickListener(this);
Bundle bundle = getArguments();
if (bundle != null) {
requestUrl = getArguments().getString(AbstListFragment.URL);
}
}
ViewGroup parent = (ViewGroup) rootView.getParent();
if (parent != null) {
parent.removeView(rootView);
}
return rootView;
}
@Override
public void onStart() {
super.onStart();
if (mListView != null) {
mListView.setRefreshing(false);
}
}
@Override
public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
page = 0;
getData(requestUrl + "&p=" + page);// 这里能够加入分页和其他请求server所须要的必要參数。比方token或者其他什么的,所以在传入的地方仅仅用传入必要的參数就OK
}
@Override
public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
page++;
getData(requestUrl + "&p=" + page);
}
protected void getData(String requestUrl) {
if (isNeedLoadDataFromNet()) {
if (page == 0) {
// 能够在这里设置载入动画
emptyView.setImageResource(R.drawable.loading_animation);// R.drawable.loading_animation代表动画资源
rocketAnimation = (AnimationDrawable) emptyView.getDrawable();
rocketAnimation.start();
}
RequestUtils.requesGet(requestUrl, this, this);
}
}
/**
* 这种方法用于返回是否是从网络载入,有些数据是须要从本地载入的。这个 方法就能够由子类来控制详细是什么
*
* @return
*/
protected boolean isNeedLoadDataFromNet() {
return true;
}
@Override
public void onResponse(JSONObject response) {
// 设置请求完成之后的状态
rocketAnimation.stop();
emptyView.setImageResource(R.drawable.nocontent);
mListView.onRefreshComplete();
}
@Override
public void onErrorResponse(VolleyError error) {
// 设置请求完成之后的状态
rocketAnimation.stop();
emptyView.setImageResource(R.drawable.nocontent);
toast("咦?网络状况貌似出了点问题.");
mListView.onRefreshComplete();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
// 当点击无数据提示的时候又一次载入
case R.id.empty_view:
mListView.setRefreshing();
break;
default:
break;
}
}
private BroadcastReceiver receiver;
@Override
public void onResume() {
super.onResume();
receiver = new NeedRefreshBroadcastReceiver();
IntentFilter filter = new IntentFilter(NEED_REFRESH_BROADCAST_RECEIVER);
filter.addCategory(Intent.CATEGORY_DEFAULT);
mContext.registerReceiver(receiver, filter);
}
@Override
public void onPause() {
super.onPause();
mContext.unregisterReceiver(receiver);
}
/**
* 主动刷新广播接收器,当数据发生改变的时候(比方加入或者删除)主动刷新
*
* @author Work
*
*/
private class NeedRefreshBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
mListView.setCurrentMode(Mode.PULL_FROM_START);
mListView.setRefreshing(false);
}
}
}
/**
* 抽象的AbstListFragment中间层,具有更强大的功能
*
* @author Work
*
*/
public abstract class SuperAbstListFragment<T> extends AbstListFragment {
protected AbstBaseAdapter<T> adapter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
try {
// 假设有些Adapter中不满足实际情况的话,能够使用反射来实例化
// adapter = (AbstBaseAdapter<T>)
// getAdapterClass().getConstructor(Context.class).newInstance(mContext);
adapter = new SuperAdapter(mContext);
mListView.setAdapter(adapter);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
/**
* 万能适配器,它仅仅是个中间件
*
* @author Work
*
*/
public class SuperAdapter extends AbstBaseAdapter<T> {
public SuperAdapter(Context context) {
super(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return SuperAbstListFragment.this.getView(position, convertView, parent);
}
}
/**
*
*
* @param position
* @param convertView
* @param parent
* @return
*/
public View getView(int position, View convertView, ViewGroup parent) {
// 这里使用的是万能的ViewHolder
ViewHolder viewHolder = ViewHolder.get(mContext, convertView, parent, R.layout.fragment_list_item, position);// 这一行能够进一步的抽取到父类中
T t = adapter.getData().get(position);
setView(viewHolder, t);
return viewHolder.getConvertView();
}
/**
* 绑定数据,使用户真正关心的仅仅有他们想要关心的
*
* @param viewHolder
* @param t
*/
public abstract void setView(ViewHolder viewHolder, T t);
/**
* 假设单单的getView方法不满足需求的话。能够通过自己定义Adapter的方法来实现,该方法用来返回须要实例化的Adapter的类名
*
* @return
*/
public Class<?> getAdapterClass() {
return null;
}
/**
* 须要解析的数据类型是一个对象还是对象的集合,由这个返回
*
* @return
*/
public abstract Type getInstanceType();
/*
* (non-Javadoc)
*
* @see
* com.sahadev.general_assembly.base.AbstListFragment#onResponse(org.json
* .JSONObject) 当网络请求成功之后回调该方法,開始解析数据
*/
@Override
public void onResponse(JSONObject response) {
super.onResponse(response);
if (response != null && response.optBoolean("success")) {
Gson gson = new Gson();
List<T> datas = gson.fromJson(response.optJSONArray("data").toString(), getInstanceType());
initAdapter(datas);
}
}
/**
* 数据解析完成之后刷新数据
*
* @param list
*/
protected void initAdapter(List<T> list) {
if (page == 0) {
adapter.addFirstPageData(list);
} else {
adapter.addOtherPageData(list);
}
}
}/**
* 含有ListFragment的Activity
*
* @author 尚斌
*
*/
public class IncludeListFragmentActivity extends FragmentActivity {
private String mFragmentClass = "x.x.x.x.x.x";
private String mRequestUrl = "http://www.baidu.com";
private String title = "标题没有定义";
public static final String TITLE = "TITLE";
public static final String CLASS = "CLASS";
public static final String URL = "URL";
/**
* @param context
* @param fragmentClass
* 须要实例化的Fragment的包名
* @param requestUrl
* 该Fragment内部的请求地址
* @return
*/
public static Intent getIntent(Context context, String fragmentClass, String requestUrl, String title) {
Intent intent = new Intent(context, IncludeListFragmentActivity.class);
Bundle bundle = new Bundle();
bundle.putString(TITLE, title);
bundle.putString(CLASS, fragmentClass);
bundle.putString(URL, requestUrl);
intent.putExtras(bundle);
return intent;
}
@SuppressWarnings("unchecked")
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
mFragmentClass = bundle.getString(CLASS);
mRequestUrl = bundle.getString(URL);
title = bundle.getString(TITLE);
// 设置标题
setTitle(title);
// 设置布局文件
setContentView(R.layout.activity_include_list_fragment);
try {
Class<BaseFragment> newInstance = (Class<BaseFragment>) Class.forName(mFragmentClass);
Method method = null;
BaseFragment fragment = null;
method = newInstance.getMethod("getInstance", String.class);
fragment = (BaseFragment) method.invoke(null, mRequestUrl);
if (fragment != null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, fragment).commit();
} else {
throw new Exception("You must be have a named getInstance method!");
}
} catch (Exception e) {
e.printStackTrace();
}
} public JsonRequest(int method, String url, Map<String, String> body, Listener<T> listener,
ErrorListener errorListener, boolean isNeedCache, Type type) {
super(method, url + "&token=token" + "&vid=vid"), errorListener);
mListener = listener;
mRequestBody = null;
mType = type;
if (isNeedCache && !(检查网络是否可用)) {
url += "&token=token" + "&vid=vid";
try {
//使用自己定义的方式去数据库中查找,这里使用的是xUtils举例:
List<Cache> datas = xUtils
.getInstance()
.getDbUtils()
.findAll(
Selector.from(Cache.class).where("requestUrl", "=", url).orderBy("time", false)
.limit(1));
if (!netAccessed && datas != null & listener != null) {
for (Cache cache : datas) {
//假设查找成功就进行回调
listener.onResponse((T) new JSONObject(cache.jsonString));
}
}
} catch (DbException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
bodyMap = body;
}网络回调部分。将server数据存储:@Override
protected void deliverResponse(final T response) {
if (response != null
&& (response.getClass().equals(String.class) || response.getClass().equals(JSONObject.class))) {
new Thread(new Runnable() {
@Override
public void run() {
Cache cache = new Cache(mUrl, response.toString());
try {
//使用xUtils进行存储
xUtils.getInstance().getDbUtils().save(cache);
} catch (DbException e) {
e.printStackTrace();
}
}
}).start();
}
netAccessed = true;
if (mListener != null && (假设网络可用)) {
if (mType != null) {
try {
String simString1 = response.getClass().getName();
String simString2 = mType.toString();
//有多种类型回调,假设仅仅是回调String类。则调用下面
if (simString2.contains(simString1)) {
mListener.onResponse(response);
} else {
mListener.onResponse(null);
}
} catch (Exception e1) {
}
} else {
//另一种是JsonObject类型,则调用下面
mListener.onResponse(response);
}
}
}大伙可能实际情况不是这个样子。可是思路可能差点儿相同,仅供參考。
当然,在该项目中还集成了不少别的主要的东西,比方ImageLoader图片载入。Volley请求工具,json解析工具等,假设是作为一个新项目的话,本项目还是能够作为一个最主要的起始项目来用用。
怎样使用ListView实现一个带有网络请求,解析,分页,缓存的公共的List页面来大大的提高工作效率
标签:complete 目的 hba other access 检查 ram 填充 man
原文地址:http://www.cnblogs.com/claireyuancy/p/6880101.html