您的位置:首页 > 移动开发 > Android开发

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

2014-12-31 16:26 357 查看

一、原应用相关模块简介

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(){

@Override
public 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);
}
}

@Override
public 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;
}

@Override
protected 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;
}

@Override
protected 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;
}

@Override
protected 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;
}

@Override
protected 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;
}

@Override
public int getCount() {
return lstTools != null ? lstTools.size() : (lstNetTools != null ? lstNetTools.size() : 0);
}

@Override
public Object getItem(int position) {
return null;
}

@Override
public long getItemId(int position) {
return 0;
}

@Override
public 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 为设置,则显示 lstNetTools
if (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();

@Override
protected 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() {

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

openNextActivity(position);
}
});
mImgLeft.setOnClickListener(new OnClickListener() {

@Override
public 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;
}

@Override
public int getCount() {
return mArrTypes.length;
}

@Override
public Object getItem(int position) {
return mArrTypes[position];
}

@Override
public long getItemId(int position) {
return 0;
}

@Override
public 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;

@Override
protected 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() {

@Override
public 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() {

@Override
public 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>() {

@Override
public 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>>() {

@Override
public 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() {

@Override
public 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;

@Override
protected 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() {

@Override
public 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;
}

// 请求服务器获取物品详情Json
AppContext.getApp()
.getNetManager()
.get(URLUtil.getURL_ZBDetail(Integer.parseInt(mStrMaterialId)),
new IListener<String>() {

@Override
public void onCall(String strJson) {

strJson = checkMaterialJson(strJson);

// 获取到Json后解析成 Material实体
AppContext.getApp()
.getJsonManager()
.parse(strJson, Material.class,
new IListener<Material>() {

@Override
public 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() {

@Override
public 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/ 。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: