一步步实现 仿制Android LOL多玩盒子(二) 物品装备相关

来源:互联网 发布:最垃圾的父母 知乎 编辑:程序博客网 时间:2024/04/29 00:41

一、原应用相关模块简介

1,入口:主界面-----游戏百科-----装备。
2,装备物品主界面中,列表选择物品类型,进入指定物品类型GridView,GridView点击某一项进入指定物品的物品详情界面。物品详情界面主要内容有:物品名称、物品价格、物品缩略图、物品属性、合成该物品所需物品,该物品可合成的物品。


二、功能分析

1,物品分类页面是一个ListView且分类是固定的;分类下装备列表是一个GridView,一共四列,每个物品包含一个图片和一个图片名称;物品详情界面包含一个ImageView,几个TextView和两个HorizontalScrollView,两个HorizontalScrollView中分别包含当前物品的合成所需和可合成物品的图标,图标点击后可进入到响应物品的物品详情界面。

2,获取某一物品分类下的所有物品的简要信息,使用 fiddler 抓包发现,访问请求格式为 http://lolbox.duowan.com/phone/apiZBItemList.php?tag=fumo ,其中tag参数的值代表物品分类,其返回值是一个Json,格式为
[{"id":3250,"text":"\u72c2\u6218\u58eb\u80eb\u7532\u2014\u5bb6\u56ed\u536b\u58eb"},{"id":3251,"text":"\u72c2\u6218\u58eb\u80eb\u7532\u2014\u7edf\u5e05"},{"id":3252,"text":"\u72c2\u6218\u58eb\u80eb\u7532\u2014\u55a7\u54d7"},{"id":3253,"text":"\u72c2\u6218\u58eb\u80eb\u7532\u2014\u5931\u771f"},{"id":3254,"text":"\u72c2\u6218\u58eb\u80eb\u7532\u2014\u6b22\u6b23"},{"id":3255,"text":"\u6cd5\u5e08\u4e4b\u9774\u2014\u5bb6\u56ed\u536b\u58eb"},{"id":3256,"text":"\u6cd5\u5e08\u4e4b\u9774\u2014\u7edf\u5e05"},{"id":3257,"text":"\u6cd5\u5e08\u4e4b\u9774\u2014\u55a7\u54d7"},{"id":3258,"text":"\u6cd5\u5e08\u4e4b\u9774\u2014\u5931\u771f"},{"id":3259,"text":"\u6cd5\u5e08\u4e4b\u9774\u2014\u6b22\u6b23"},{"id":3260,"text":"\u5fcd\u8005\u8db3\u5177\u2014\u5bb6\u56ed\u536b\u58eb"},{"id":3261,"text":"\u5fcd\u8005\u8db3\u5177\u2014\u7edf\u5e05"},{"id":3262,"text":"\u5fcd\u8005\u8db3\u5177\u2014\u55a7\u54d7"},{"id":3263,"text":"\u5fcd\u8005\u8db3\u5177\u2014\u5931\u771f"},{"id":3264,"text":"\u5fcd\u8005\u8db3\u5177\u2014\u6b22\u6b23"},{"id":3265,"text":"\u6c34\u94f6\u4e4b\u9774\u2014\u5bb6\u56ed\u536b\u58eb"},{"id":3266,"text":"\u6c34\u94f6\u4e4b\u9774\u2014\u7edf\u5e05"},{"id":3267,"text":"\u6c34\u94f6\u4e4b\u9774\u2014\u55a7\u54d7"},{"id":3268,"text":"\u6c34\u94f6\u4e4b\u9774\u2014\u5931\u771f"},{"id":3269,"text":"\u6c34\u94f6\u4e4b\u9774\u2014\u6b22\u6b23"},{"id":3270,"text":"\u75be\u884c\u4e4b\u9774\u2014\u5bb6\u56ed\u536b\u58eb"},{"id":3271,"text":"\u75be\u884c\u4e4b\u9774\u2014\u7edf\u5e05"},{"id":3272,"text":"\u75be\u884c\u4e4b\u9774\u2014\u55a7\u54d7"},{"id":3273,"text":"\u75be\u884c\u4e4b\u9774\u2014\u5931\u771f"},{"id":3274,"text":"\u75be\u884c\u4e4b\u9774\u2014\u6b22\u6b23"},{"id":3275,"text":"\u660e\u6717\u4e4b\u9774\u2014\u5bb6\u56ed\u536b\u58eb"},{"id":3276,"text":"\u660e\u6717\u4e4b\u9774\u2014\u7edf\u5e05"},{"id":3277,"text":"\u660e\u6717\u4e4b\u9774\u2014\u55a7\u54d7"},{"id":3278,"text":"\u660e\u6717\u4e4b\u9774\u2014\u5931\u771f"},{"id":3279,"text":"\u660e\u6717\u4e4b\u9774\u2014\u6b22\u6b23"},{"id":3280,"text":"\u8f7b\u7075\u4e4b\u9774\u2014\u5bb6\u56ed\u536b\u58eb"},{"id":3281,"text":"\u8f7b\u7075\u4e4b\u9774\u2014\u7edf\u5e05"},{"id":3282,"text":"\u8f7b\u7075\u4e4b\u9774\u2014\u55a7\u54d7"},{"id":3283,"text":"\u8f7b\u7075\u4e4b\u9774\u2014\u5931\u771f"},{"id":3284,"text":"\u8f7b\u7075\u4e4b\u9774\u2014\u6b22\u6b23"}]
结果只包含物品ID和物品名称,继续查看抓包信息可知, 由物品id取物品缩略图的 请求格式为 http://img.lolbox.duowan.com/zb/3250_64x64.png ,最后一部分下划线前是物品id,下划线后是要取的图片的大小。至此,获取指定分类的物品列表的功能所需条件已经完备。

3,获取某一物品的详细信息的请求格式为 http://lolbox.duowan.com/phone/apiItemDetail.php?id=3093,其中id参数的值代表物品的ID,请求结果是Json,格式为
{"id":"3093","name":"\u8d2a\u5a6a\u4e4b\u5203","description":"+10%\u66b4\u51fb\u51e0\u7387\uff0c\u552f\u4e00\u88ab\u52a8\u2014\u8d2a\u8d22\uff1a\u6bcf10\u79d2\u83b7\u5f97+3\u679a\u91d1\u5e01\u3002\u552f\u4e00\u88ab\u52a8\u2014\u8d2a\u5a6a\uff1a\u6bcf\u6b21\u51fb\u6740\u5355\u4f4d\u65f6\u989d\u5916\u83b7\u5f972\u679a\u91d1\u5e01\u3002\u53ef\u4ee5\u4e0e\u5176\u5b83\u91d1\u5e01\u6536\u5165\u578b\u88c5\u5907\u5171\u5b58","price":400,"allPrice":800,"sellPrice":320,"tags":" ","extAttrs":{"FlatCritChanceMod":0.1},"need":"1051","compose":"3087,3142","extDesc":"\u552f\u4e00\u88ab\u52a8\u2014\u8d2a\u8d22\uff1a\u6bcf10\u79d2\u83b7\u5f97+3\u679a\u91d1\u5e01\u3002\u552f\u4e00\u88ab\u52a8\u2014\u8d2a\u5a6a\uff1a\u6bcf\u6b21\u51fb\u6740\u5355\u4f4d\u65f6\u989d\u5916\u83b7\u5f972\u679a\u91d1\u5e01\u3002\u53ef\u4ee5\u4e0e\u5176\u5b83\u91d1\u5e01\u6536\u5165\u578b\u88c5\u5907\u5171\u5b58\u3002"}
结果中包含了当前物品 的ID、名称、价格、属性、合成所需物品的ID、可合成物品的ID。依据这些属性再结合前面根据ID获取物品图片的方式,即可把物品详情界面中的元素完全展示出来。

三、功能实现

1,几个工具类
/** * 路径工具 * @author yangsheng * @date 2014年12月30日 */public class URLUtil {/** * 取某分类的装备列表Json的请求URL * @param type * @return */public static final String getURL_ZBLst(EnumZBType type){return String.format("http://lolbox.duowan.com/phone/apiZBItemList.php?tag=%s", type.toString());}/** * 取装备图片的请求URL * @param zbId 装备id * @param dpi  图片分辨率 * @return */public static final String getURL_ZBImg(int zbId, EnumDPI dpi){return String.format("http://img.lolbox.duowan.com/zb/%s_%s.png", zbId, dpi.toDPIString());}/** * 取装备详细信息Json的请求URL * @param zbId * @return */public static final String getURL_ZBDetail(int zbId){return String.format("http://lolbox.duowan.com/phone/apiItemDetail.php?id=%s", zbId);}}
将网络请求操作统一封装在一个管理器中,方便统一管理
/** * 全局的网络请求管理器 * @author warren * @date 2014年12月30日 */public class AppNetManager {private static AppNetManager netManager;private LruCache<String, String> cache = new LruCache<String, String>(1000);/** * 线程安全地取唯一实例 * @return */public static AppNetManager getInstance(){if(netManager == null){synchronized (AppNetManager.class) {if(netManager == null){netManager = new AppNetManager();}}}return netManager;}private AppNetManager(){}/** * 异步请求指定URL,同步回调 * @param strUrl * @param listener */public void get(final String strUrl, final IListener<String> listener){String strHistory = cache.get(strUrl);if(strHistory != null){listener.onCall(strHistory);return;}AsyncHttpClient httpClient = new AsyncHttpClient();httpClient.get(strUrl, new AsyncHttpResponseHandler(){@Overridepublic void onSuccess(int arg0, Header[] arg1, byte[] arg2) {super.onSuccess(arg0, arg1, arg2);try {String strResult = new String(arg2, "UTF-8");cache.put(strUrl, strResult);listener.onCall(strResult);} catch (UnsupportedEncodingException e) {LogTool.exception(e);listener.onCall(null);}}@Overridepublic void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {super.onFailure(arg0, arg1, arg2, arg3);listener.onCall(null);}});}

Json比较大时,解析操作是比较耗时的,这里把解析操作封装为异步解析,同步回调。
/** * Json解析管理器 * @author warren * @date 2014年12月31日 */public class AppJsonParserManager {private static AppJsonParserManager jpm;public static AppJsonParserManager getInstance() {if (jpm == null) {synchronized (AppJsonParserManager.class) {if (jpm == null) {jpm = new AppJsonParserManager();}}}return jpm;}private AppJsonParserManager() {}/** * 异步解析Json,同步回调。解析成功则回调方法中的参数是解析结果,否则是 null * @param strJson * @param cls * @param listener */public <T> void parse(final String strJson, final Class<T> cls, final IListener<T> listener) {new AsyncTaskParser<T>(listener, cls).execute(strJson);}/** * 异步解析列表Json,同步回调。解析成功则回调方法中的参数是解析结果,否则是 null。 * @param strJson * @param cls * @param listener */public <T> void parseList(final String strJson, final Class<T> cls,final IListener<List<T>> listener) {new AsyncTaskParserList<T>(cls, listener).execute(strJson);}/** * 异步解析列表Json,同步回调 * @author warren * @date 2014年12月31日 * @param <T> */class AsyncTaskParserList<T> extends AsyncTask<String, Integer, List<T>> {private Class<T> cls;private IListener<List<T>> listener;public AsyncTaskParserList(Class<T> cls, IListener<List<T>> listener) {this.listener = listener;this.cls = cls;}@Overrideprotected List<T> doInBackground(String... params) {StringReader sr = new StringReader(params[0]);List<T> lst = new ArrayList<T>();try {sr.reset();// 解析成List时,无法直接解析成指定类型的列表,所以需要把解析得到的List<HashMap<String,// Object>>每一项单独再转成指定类型的对象。JsonFactory factory = new ObjectMapper().getJsonFactory();JsonParser jpar = factory.createJsonParser(sr);List<HashMap<String, Object>> mapLst = jpar.readValueAs(List.class);for (HashMap<String, Object> map : mapLst) {// 先将Map转换为Json字符串,再把Json字符串重新转换为指定类型的对象。StringWriter sw = new StringWriter();factory.createJsonGenerator(sw).writeObject(map);T t = factory.createJsonParser(sw.toString()).readValueAs(cls);lst.add(t);sw.close();}} catch (Exception e) {LogTool.exception(e);}sr.close();return lst;}@Overrideprotected void onPostExecute(List<T> result) {super.onPostExecute(result);listener.onCall(result);}}/** * 异步解析Json,同步回调 * @author warren * @date 2014年12月31日 * @param <T> */class AsyncTaskParser<T> extends AsyncTask<String, Integer, T> {private IListener<T> listener;;private Class<T> cls;public AsyncTaskParser(IListener<T> listener, Class<T> cls) {this.listener = listener;this.cls = cls;}@Overrideprotected T doInBackground(String... params) {StringReader sr = new StringReader(params[0]);T obj = null;try {JsonParser jpar = new ObjectMapper().getJsonFactory().createJsonParser(sr);obj = jpar.readValueAs(cls);} catch (Exception e) {LogTool.exception(e);}sr.close();return obj;}@Overrideprotected void onPostExecute(T result) {super.onPostExecute(result);listener.onCall(result);}}

GridView的通用适配器
/** * 通用的GridView的Adapter,支持 {@link SimpleTool} 和 {@link SimpleNetTool}列表的显示 * @author yangsheng * @date 2014年12月31日 */public class BaseGridAdapter extends BaseAdapter {private LayoutInflater inflater;private List<SimpleTool> lstTools;private List<SimpleNetTool> lstNetTools;private ImageLoader imgLoader;private DisplayImageOptions options;private int numColumn = 3;public BaseGridAdapter(LayoutInflater inflater) {this.inflater = inflater;}public void setLstTools(List<SimpleTool> lstTools) {this.lstTools = lstTools;}public void setLstNetTools(List<SimpleNetTool> lstNetTools, ImageLoader imgLoader, DisplayImageOptions options) {this.lstNetTools = lstNetTools;this.imgLoader = imgLoader;this.options = options;}/** * @return the numColumn */public int getNumColumn() {return numColumn;}/** * @param numColumn the numColumn to set */public void setNumColumn(int numColumn) {this.numColumn = numColumn;}@Overridepublic int getCount() {return lstTools != null ? lstTools.size() : (lstNetTools != null ? lstNetTools.size() : 0);}@Overridepublic Object getItem(int position) {return null;}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = inflater.inflate(R.layout.griditem, parent, false);holder = new ViewHolder();holder.img = (ImageView) convertView.findViewById(R.id.img);holder.tv = (TextView) convertView.findViewById(R.id.tv);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}// 优先显示 lstTools,如果 lstTools 为设置,则显示 lstNetToolsif (lstTools != null) {holder.img.setImageResource(lstTools.get(position).getImgResId());holder.tv.setText(lstTools.get(position).getTxtResId());} else {imgLoader.displayImage(lstNetTools.get(position).getStrImgUrl(), holder.img, options);holder.tv.setText(lstNetTools.get(position).getStrText());}AbsListView.LayoutParams param = new AbsListView.LayoutParams(parent.getWidth() / numColumn, android.view.ViewGroup.LayoutParams.MATCH_PARENT);convertView.setLayoutParams(param);return convertView;}class ViewHolder {ImageView img;TextView tv;}}
物品分类界面
/** * 物品分类 * @author warren * @date 2014年12月31日 */public class MaterialTypesActivity extends Activity {private ImageView mImgLeft;private ImageView mImgRight;private TextView mTvTitle;private ListView mLvLst;private String[] mArrTypes = EnumZBType.getStringTypeArray();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_baike);initCtrl();}private void initCtrl() {mImgLeft = (ImageView) findViewById(R.id.img_title_left);mImgRight = (ImageView) findViewById(R.id.img_title_right);mTvTitle = (TextView) findViewById(R.id.tv_title);mImgLeft.setImageResource(R.drawable.lolbox_titleview_return_default);mImgRight.setVisibility(View.GONE);mTvTitle.setText("物品分类");mLvLst = (ListView) findViewById(R.id.lv_types);AdapterList adapter = new AdapterList(LayoutInflater.from(this), mArrTypes);mLvLst.setAdapter(adapter);mLvLst.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {openNextActivity(position);}});mImgLeft.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {finish();}});}/** * 打开物品列表Activity * @param position */private void openNextActivity(int position) {Intent it = new Intent(this, MaterialGridWithTypeActivity.class);it.putExtra(MaterialGridWithTypeActivity.EXTRA_ZBTYPE, mArrTypes[position]);startActivity(it);overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);}class AdapterList extends BaseAdapter {private LayoutInflater mInflater;private String[] mArrTypes;public AdapterList(LayoutInflater inflater,  String[] arrType) {this.mInflater = inflater;this.mArrTypes = arrType;}@Overridepublic int getCount() {return mArrTypes.length;}@Overridepublic Object getItem(int position) {return mArrTypes[position];}@Overridepublic long getItemId(int position) {return 0;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = mInflater.inflate(R.layout.activity_baike_listitem, parent, false);holder = new ViewHolder();holder.img = (ImageView) convertView.findViewById(R.id.img);holder.tv = (TextView) convertView.findViewById(R.id.tv);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.img.setVisibility(View.GONE);holder.tv.setText(mArrTypes[position]);return convertView;}class ViewHolder {public ImageView img;public TextView tv;}}}

特定分类下的物品列表

/** * 特定分类下的物品列表 * @author warren * @date 2014年12月31日 */public class MaterialGridWithTypeActivity extends Activity {public static final String EXTRA_ZBTYPE = "EXTRA_ZBTYPE";private ImageView mImgLeft;private ImageView mImgRight;private TextView mTvTitle;private GridView mGv;private String mStrTitle;private EnumZBType mEnumType;private BaseGridAdapter mAdapter;private List<MaterialSimple> mLstMs;private List<SimpleNetTool> mLstSnt;private DisplayImageOptions mDisPlayOption;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_grid);String strType = getIntent().getStringExtra(EXTRA_ZBTYPE);if (StringUtils.isNullOrZero(strType)) {mStrTitle = "全部装备";mEnumType = EnumZBType.all;} else {mStrTitle = strType;mEnumType = EnumZBType.getZbType(StringUtils.getIndex(EnumZBType.getStringTypeArray(),strType));}initImgOption();initCtrl();}private void initImgOption() {// 这里无需设置这么多,一般使用ImageLoader的默认DisplayImageOptions就可以满足需求Options opt = new Options();opt.inInputShareable = true;opt.inPurgeable = true;opt.inPreferredConfig = Bitmap.Config.RGB_565;opt.inSampleSize = 1;mDisPlayOption = new DisplayImageOptions.Builder().considerExifParams(true).bitmapConfig(Config.RGB_565).decodingOptions(opt).displayer(new BitmapDisplayer() {@Overridepublic void display(Bitmap arg0, ImageAware arg1, LoadedFrom arg2) {// 由于请求的图片较小,在分辨率较大的设备上显示不美观。这里在显示前先放大到两倍,再显示。// 放大到两倍后,经检查大部分手机分辨率都能较好地展示,而放大后的图片对某一分辨率来说太大时,// 可通过设置ImageView的ScaleType来将自动将图片缩小。Matrix matrix = new Matrix();matrix.postScale(2, 2); Bitmap bitResize = Bitmap.createBitmap(arg0, 0, 0, arg0.getWidth(),arg0.getHeight(), matrix, true);arg1.setImageBitmap(bitResize);}}).cacheInMemory(true).showImageOnLoading(R.drawable.dl_loading_img).imageScaleType(ImageScaleType.IN_SAMPLE_INT).build();}private void initCtrl() {mImgLeft = (ImageView) findViewById(R.id.img_title_left);mImgRight = (ImageView) findViewById(R.id.img_title_right);mTvTitle = (TextView) findViewById(R.id.tv_title);mImgLeft.setImageResource(R.drawable.lolbox_titleview_return_default);mImgRight.setVisibility(View.GONE);mTvTitle.setText(mStrTitle);mImgLeft.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {finish();}});mGv = (GridView) findViewById(R.id.grid);mGv.setNumColumns(4);mAdapter = new BaseGridAdapter(LayoutInflater.from(this));GridParams params = GridParams.createNormal();params.imgFillRootWidth = true;mAdapter.setNumColumn(4);mGv.setAdapter(mAdapter);// 请求服务器,查询某一类型的物品列表AppContext.getApp().getNetManager().get(URLUtil.getURL_ZBLst(mEnumType), new IListener<String>() {@Overridepublic void onCall(String t) {if (t == null) {Toast.makeText(MaterialGridWithTypeActivity.this, "没有符合条件的物品",Toast.LENGTH_SHORT).show();return;}// 获得物品列表Json后,转换为所需要的对象列表AppContext.getApp().getJsonManager().parseList(t, MaterialSimple.class,new IListener<List<MaterialSimple>>() {@Overridepublic void onCall(List<MaterialSimple> lstMs) {if(lstMs == null || lstMs.size() == 0){Toast.makeText(MaterialGridWithTypeActivity.this, "没有符合条件的物品",Toast.LENGTH_SHORT).show();return;}mLstMs = lstMs;// 依据物品id,构造物品的图片地址,在Adapter中将根据该地址获取对应的图片mLstSnt = new ArrayList<SimpleNetTool>();for (MaterialSimple ms : lstMs) {SimpleNetTool snt = new SimpleNetTool(URLUtil.getURL_ZBImg(ms.getId(),EnumDPI.DPI64x64), ms.getText());mLstSnt.add(snt);}mAdapter.setLstNetTools(mLstSnt, AppContext.getApp().getImgLoader(), mDisPlayOption);mAdapter.notifyDataSetChanged();}});}});mGv.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {openMaterialDetail("" + mLstMs.get(position).getId());}});}/** * 打开物品详情界面 * @param materialId */private void openMaterialDetail(String materialId) {Intent it = new Intent(this, MaterialDetailActivity.class);it.putExtra(MaterialDetailActivity.EXTRA_MATERIALID, materialId);startActivity(it);overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);}}

物品详情界面
/** * 物品详情 * @author warren * @date 2014年12月31日 */public class MaterialDetailActivity extends Activity {public static final String EXTRA_MATERIALID = "EXTRA_MATERIALID";private ImageView mImgLeft;private ImageView mImgRight;private TextView mTvTitle;private LinearLayout mLlRoot;private ImageView mImgMaterial;private TextView mTvMaterialName;private TextView mTvMaterialPrice;private TextView mTvDescription;private LinearLayout mLlNeed;private LinearLayout mLlCompose;private ImageLoader mImgLoader;private String mStrMaterialId;private Material mMaterial;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_materialdetail);mImgLoader = AppContext.getApp().getImgLoader();mStrMaterialId = getIntent().getStringExtra(EXTRA_MATERIALID);initCtrl();}private void initCtrl() {mImgLeft = (ImageView) findViewById(R.id.img_title_left);mImgRight = (ImageView) findViewById(R.id.img_title_right);mTvTitle = (TextView) findViewById(R.id.tv_title);mImgLeft.setImageResource(R.drawable.lolbox_titleview_return_default);mImgRight.setVisibility(View.GONE);mTvTitle.setText("物品详情");mImgLeft.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {finish();}});mLlRoot = (LinearLayout) findViewById(R.id.ll_root);mLlNeed = (LinearLayout) findViewById(R.id.ll_need);mLlCompose = (LinearLayout) findViewById(R.id.ll_compose);mImgMaterial = (ImageView) findViewById(R.id.img_material);mTvMaterialName = (TextView) findViewById(R.id.tv_materialname);mTvMaterialPrice = (TextView) findViewById(R.id.tv_materialmoney);mTvDescription = (TextView) findViewById(R.id.tv_materialdescription);if (mStrMaterialId == null) {setNullHint();return;}// 请求服务器获取物品详情JsonAppContext.getApp().getNetManager().get(URLUtil.getURL_ZBDetail(Integer.parseInt(mStrMaterialId)),new IListener<String>() {@Overridepublic void onCall(String strJson) {strJson = checkMaterialJson(strJson);// 获取到Json后解析成 Material实体AppContext.getApp().getJsonManager().parse(strJson, Material.class,new IListener<Material>() {@Overridepublic void onCall(Material material) {if (material == null) {setNullHint();return;}mMaterial = material;setView();}});}});}/** * 纠正服务器传回的Json。 * @description *              请求生命药水、法力药水等“没有需求物品也没有合成物品”的工具类物品的物品详情时,服务器返回的Json中, *              extAtts的值是 "extAttrs":[] 格式,这与Material *              类的extAttrs所需求的Map格式不符,需矫正,否则会解析失败。 * @param strJson * @return */private String checkMaterialJson(String strJson) {if (strJson.contains("\"extAttrs\":[]")) {strJson = strJson.replace("\"extAttrs\":[]", "\"extAttrs\":{}");}return strJson;}/** * 依据物品详情设置界面 */private void setView() {mTvDescription.setText(mMaterial.getDescription());mTvMaterialName.setText(mMaterial.getName());mTvMaterialPrice.setText("价格:" + mMaterial.getPrice() + " 总价:" + mMaterial.getAllPrice()+ " 售价:" + mMaterial.getSellPrice());mImgLoader.displayImage(URLUtil.getURL_ZBImg(Integer.parseInt(mMaterial.getId()), EnumDPI.DPI64x64),mImgMaterial);String[] arrNeedId = mMaterial.getNeed() == null ? null : mMaterial.getNeed().split(",");String[] arrComposeId = mMaterial.getCompose() == null ? null : mMaterial.getCompose().split(",");if (arrNeedId != null) {for (String strNeedId : arrNeedId) {if (StringUtils.isNullOrZero(strNeedId)) {continue;}mLlNeed.addView(createMaterialImg(strNeedId));}}if (arrComposeId != null) {for (String strComposeId : arrComposeId) {if (StringUtils.isNullOrZero(strComposeId)) {continue;}mLlCompose.addView(createMaterialImg(strComposeId));}}}/** * 设置查找物品详情失败的提示 */private void setNullHint() {mLlRoot.removeAllViews();TextView tvHint = new TextView(this);tvHint.setText("查找物品详情失败");mLlRoot.addView(tvHint);}/** * 根据物品ID构建对应的ImageView,所需图片从服务器请求,点击事件也已在这里设置。 * @param materialId * @return */private ImageView createMaterialImg(final String materialId) {ImageView img = new ImageView(this);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(DeviceUtil.dp2Px(this, 40), DeviceUtil.dp2Px(this, 40));params.leftMargin = DeviceUtil.dp2Px(this, 2);params.rightMargin = DeviceUtil.dp2Px(this, 2);img.setLayoutParams(params);mImgLoader.displayImage(URLUtil.getURL_ZBImg(Integer.parseInt(materialId), EnumDPI.DPI64x64), img);img.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {openMaterialDetail(materialId);}});return img;}/** * 打开物品详情界面 * @param materialId */private void openMaterialDetail(String materialId) {Intent it = new Intent(this, MaterialDetailActivity.class);it.putExtra(MaterialDetailActivity.EXTRA_MATERIALID, materialId);startActivity(it);overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);}}

/** * 物品bean * @author warren * @date 2014年12月30日 */public class Material {private String id;private String name;private String description;private Map<String, String> extAttrs;private String need;private String compose;private String extDesc;private int price;private int allPrice;private int sellPrice;private String tags;public Material() {super();}/** * @return the id */public String getId() {return id;}/** * @param id the id to set */public void setId(String id) {this.id = id;}/** * @return the name */public String getName() {return name;}/** * @param name the name to set */public void setName(String name) {this.name = name;}/** * @return the description */public String getDescription() {return description;}/** * @param description the description to set */public void setDescription(String description) {this.description = description;}/** * @return the extAttrs */public Map<String, String> getExtAttrs() {return extAttrs;}/** * @param extAttrs the extAttrs to set */public void setExtAttrs(Map<String, String> extAttrs) {this.extAttrs = extAttrs;}/** * @return the need */public String getNeed() {return need;}/** * @param need the need to set */public void setNeed(String need) {this.need = need;}/** * @return the compose */public String getCompose() {return compose;}/** * @param compose the compose to set */public void setCompose(String compose) {this.compose = compose;}/** * @return the extDesc */public String getExtDesc() {return extDesc;}/** * @param exDesc the exDesc to set */public void setExtDesc(String extDesc) {this.extDesc = extDesc;}/** * @return the price */public int getPrice() {return price;}/** * @param price the price to set */public void setPrice(int price) {this.price = price;}/** * @return the allPrice */public int getAllPrice() {return allPrice;}/** * @param allPrice the allPrice to set */public void setAllPrice(int allPrice) {this.allPrice = allPrice;}/** * @return the sellPrice */public int getSellPrice() {return sellPrice;}/** * @param sellPrice the sellPrice to set */public void setSellPrice(int sellPrice) {this.sellPrice = sellPrice;}/** * @return the tags */public String getTags() {return tags;}/** * @param tags the tags to set */public void setTags(String tags) {this.tags = tags;}}

/** * 简化版的物品bean * @author warren * @date 2014年12月31日 */public class MaterialSimple {private int id;private String text;public MaterialSimple(){}public MaterialSimple(int id, String text) {super();this.id = id;this.text = text;}/** * @return the id */public int getId() {return id;}/** * @param id the id to set */public void setId(int id) {this.id = id;}/** * @return the text */public String getText() {return text;}/** * @param text the text to set */public void setText(String text) {this.text = text;}}

四、实现效果



五、说明

1,这些代码中使用到的 jar 包有 universal-image-loader, android-async-http, jacksonjson.
2,图片的请求使用 universal-image-loader来做缓存就已足够,其他网络访问的请求 暂时只做了内存缓存,没有存放在本地;官方应用的很多数据都是存放在了本地的,本地数据过期时会提醒下载最新的数据包;本地缓存的功能留待以后做。
3,由于官方应用的很多数据做了本地缓存,所以在操作功能时经常会不用 请求服务器,为了方便分析,可以把本地缓存清掉。缓存路径为 /sdcard/lolboxcache/      。

0 0
原创粉丝点击