Lost and Found(结对项目)功能实现
Lost and Found(失物招领APP)
Lost and Found(失物招领APP)是以Bmob为基础的,参考了网上的案例。主要实现物品的发布、修改、呈现和删除。使用场景如下:用户捡到物品,打开手机软件,填写物品的招领信息(标题、描述和联系方式);用户丢失物品,打开手机软件,填写物品的丢失信息(标题、描述和联系方式);任何人都可以查看到失物和招领的信息列表,可以对发布的信息进行删除。该项目将使用到Bmob的以下几个功能:
1、 添加数据
添加失物/招领信息到服务器中。
2、 查找数据
在列表中显示所有用户发布的失物/招领信息。
3、 删除数据
删除已发布的失物/招领信息。
部分界面效果如下:
进入动画 主界面
失物信息界面添加失物信息界面
失物列表 编辑删除
数据结构设计
失物表(Lost) | ||
字段名 | 类型 | 描述 |
describe | String | 失物的描述信息 |
phone | String | 联系的手机号码 |
title | String | 失物的标题信息 |
招领表(Found) | ||
字段名 | 类型 | 描述 |
describe | String | 招领的描述信息 |
phone | String | 联系的手机号码 |
title | String | 招领的标题信息 |
初始化SDK
Bmob为每个应用都提供了一个唯一标识,使用Bmob开发的应用都要首先使用这个Application ID”进行初始化(在前面博客中已经提到)。对应代码如下:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //初始化 Bmob SDK,第一个参数为上下文,第二个参数为Application ID Bmob.initialize(this, Constants.Bmob_APPID); //其他代码 }
Lost类和Found类
为操作Bmob的云端数据库,SDK首先需要创建数据表对应的模型类(模型类的名称必须和云端数据表的名称一致),该类需要继承自BmobObject,实现刚刚创建的数据表字段的set和get方法(系统默认字段objectId、createAt、updateAt不需要声明)。因为项目需要操作Lost表和Found表,因此需要创建Lost类和Found类。
创建失物对象
public class Lost extends BmobObject{ private String title;//标题 private String describe;//描述 private String phone;//联系手机 public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescribe() { return describe; } public void setDescribe(String describe) { this.describe = describe; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
创建招领对象
public class Found extends BmobObject { private String title;//标题 private String describe;//描述 private String phone;//联系手机 public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescribe() { return describe; } public void setDescribe(String describe) { this.describe = describe; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }
添加失物/招领信息
用户填写了失物信息之后,只需要构造一个Lost实例,然后简单调用模型类的insertObject方法就可以将信息添加到云数据库中,实现代码如下:
public class AddActivity extends BaseActivity implements OnClickListener { EditText edit_title, edit_photo, edit_describe; Button btn_back, btn_true; TextView tv_add; String from = ""; String old_title = ""; String old_describe = ""; String old_phone = ""; @Override public void setContentView() { // TODO Auto-generated method stub setContentView(R.layout.activity_add); } @Override public void initViews() { // TODO Auto-generated method stub tv_add = (TextView) findViewById(R.id.tv_add); btn_back = (Button) findViewById(R.id.btn_back); btn_true = (Button) findViewById(R.id.btn_true); edit_photo = (EditText) findViewById(R.id.edit_photo); edit_describe = (EditText) findViewById(R.id.edit_describe); edit_title = (EditText) findViewById(R.id.edit_title); } @Override public void initListeners() { // TODO Auto-generated method stub btn_back.setOnClickListener(this); btn_true.setOnClickListener(this); } @Override public void initData() { // TODO Auto-generated method stub from = getIntent().getStringExtra("from"); old_title = getIntent().getStringExtra("title"); old_phone = getIntent().getStringExtra("phone"); old_describe = getIntent().getStringExtra("describe"); edit_title.setText(old_title); edit_describe.setText(old_describe); edit_photo.setText(old_phone); if (from.equals("Lost")) { tv_add.setText("添加失物信息"); } else { tv_add.setText("添加招领信息"); } } @Override public void onClick(View v) { // TODO Auto-generated method stub if (v == btn_true) { addByType(); } else if (v == btn_back) { finish(); } } String title = ""; String describe = ""; String photo=""; /**根据类型添加失物/招领 * */ private void addByType(){ title = edit_title.getText().toString(); describe = edit_describe.getText().toString(); photo = edit_photo.getText().toString(); if(TextUtils.isEmpty(title)){ ShowToast("请填写标题"); return; } if(TextUtils.isEmpty(describe)){ ShowToast("请填写描述"); return; } if(TextUtils.isEmpty(photo)){ ShowToast("请填写手机"); return; } if(from.equals("Lost")){ addLost(); }else{ addFound(); } } private void addLost(){ Lost lost = new Lost(); lost.setDescribe(describe); lost.setPhone(photo); lost.setTitle(title); lost.save(this, new SaveListener() { @Override public void onSuccess() { // TODO Auto-generated method stub ShowToast("失物信息添加成功!"); setResult(RESULT_OK); finish(); } @Override public void onFailure(int code, String arg0) { // TODO Auto-generated method stub ShowToast("添加失败:"+arg0); } }); } private void addFound(){ Found found = new Found(); found.setDescribe(describe); found.setPhone(photo); found.setTitle(title); found.save(this, new SaveListener() { @Override public void onSuccess() { // TODO Auto-generated method stub ShowToast("招领信息添加成功!"); setResult(RESULT_OK); finish(); } @Override public void onFailure(int code, String arg0) { // TODO Auto-generated method stub ShowToast("添加失败:"+arg0); } }); } }
获取失物/招领列表、删除失物招领信息
项目使用到Bmob提供的最简单的查询和排序功能,直接调用BmobQuery类的findObjects方法和order方法来获取失物列表。从云数据库中删除某条记录需要设置这个要删除的ObjectId的信息,再调用模型类的deleteObject方法就可以了,实现代码如下
public class MainActivity extends BaseActivity implements OnClickListener, IPopupItemClick, OnItemLongClickListener { RelativeLayout layout_action;// LinearLayout layout_all; TextView tv_lost; ListView listview; Button btn_add; protected QuickAdapter<Lost> LostAdapter;// 失物 protected QuickAdapter<Found> FoundAdapter;// 招领 private Button layout_found; private Button layout_lost; PopupWindow morePop; RelativeLayout progress; LinearLayout layout_no; TextView tv_no; @Override public void setContentView() { // TODO Auto-generated method stub setContentView(R.layout.activity_main); } @Override public void initViews() { // TODO Auto-generated method stub progress = (RelativeLayout) findViewById(R.id.progress); layout_no = (LinearLayout) findViewById(R.id.layout_no); tv_no = (TextView) findViewById(R.id.tv_no); layout_action = (RelativeLayout) findViewById(R.id.layout_action); layout_all = (LinearLayout) findViewById(R.id.layout_all); // 默认是失物界面 tv_lost = (TextView) findViewById(R.id.tv_lost); tv_lost.setTag("lost"); listview = (ListView) findViewById(R.id.list_lost); btn_add = (Button) findViewById(R.id.btn_add); // 初始化长按弹窗 initEditPop(); } @Override public void initListeners() { // TODO Auto-generated method stub listview.setOnItemLongClickListener(this); btn_add.setOnClickListener(this); layout_all.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub if (v == layout_all) { showListPop(); } else if (v == btn_add) { Intent intent = new Intent(this, AddActivity.class); intent.putExtra("from", tv_lost.getTag().toString()); startActivityForResult(intent, Constants.REQUESTCODE_ADD); } else if (v == layout_found) { changeTextView(v); morePop.dismiss(); queryFounds(); } else if (v == layout_lost) { changeTextView(v); morePop.dismiss(); queryLosts(); } } @Override public void initData() { // TODO Auto-generated method stub if (LostAdapter == null) { LostAdapter = new QuickAdapter<Lost>(this, R.layout.item_list) { @Override protected void convert(BaseAdapterHelper helper, Lost lost) { helper.setText(tv_title, lost.getTitle()) .setText(tv_describe, lost.getDescribe()) .setText(tv_time, lost.getCreatedAt()) .setText(tv_photo, lost.getPhone()); } }; } if (FoundAdapter == null) { FoundAdapter = new QuickAdapter<Found>(this, R.layout.item_list) { @Override protected void convert(BaseAdapterHelper helper, Found found) { helper.setText(tv_title, found.getTitle()) .setText(tv_describe, found.getDescribe()) .setText(tv_time, found.getCreatedAt()) .setText(tv_photo, found.getPhone()); } }; } listview.setAdapter(LostAdapter); // 默认加载失物界面 queryLosts(); } private void changeTextView(View v) { if (v == layout_found) { tv_lost.setTag("Found"); tv_lost.setText("Found"); } else { tv_lost.setTag("Lost"); tv_lost.setText("Lost"); } } @SuppressWarnings("deprecation") private void showListPop() { View view = LayoutInflater.from(this).inflate(R.layout.pop_lost, null); // 注入 layout_found = (Button) view.findViewById(R.id.layout_found); layout_lost = (Button) view.findViewById(R.id.layout_lost); layout_found.setOnClickListener(this); layout_lost.setOnClickListener(this); morePop = new PopupWindow(view, mScreenWidth, 600); morePop.setTouchInterceptor(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { morePop.dismiss(); return true; } return false; } }); morePop.setWidth(WindowManager.LayoutParams.MATCH_PARENT); morePop.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); morePop.setTouchable(true); morePop.setFocusable(true); morePop.setOutsideTouchable(true); morePop.setBackgroundDrawable(new BitmapDrawable()); // 动画效果 从顶部弹下 morePop.setAnimationStyle(R.style.MenuPop); morePop.showAsDropDown(layout_action, 0, -dip2px(this, 2.0F)); } private void initEditPop() { mPopupWindow = new EditPopupWindow(this, 200,48); mPopupWindow.setOnPopupItemClickListner(this); } EditPopupWindow mPopupWindow; int position; @Override public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // TODO Auto-generated method stub position = arg2; int[] location = new int[2]; arg1.getLocationOnScreen(location); mPopupWindow.showAtLocation(arg1, Gravity.RIGHT | Gravity.TOP, location[0], getStateBar() + location[1]); return false; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if (resultCode != RESULT_OK) { return; } switch (requestCode) { case Constants.REQUESTCODE_ADD:// 添加成功之后的回调 String tag = tv_lost.getTag().toString(); if (tag.equals("Lost")) { queryLosts(); } else { queryFounds(); } break; } } /** * 查询全部失物信息 queryLosts * * */ private void queryLosts() { showView(); BmobQuery<Lost> query = new BmobQuery<Lost>(); query.order("-createdAt");// 按照时间降序 query.findObjects(this, new FindListener<Lost>() { @Override public void onSuccess(List<Lost> losts) { // TODO Auto-generated method stub LostAdapter.clear(); FoundAdapter.clear(); if (losts == null || losts.size() == 0) { showErrorView(0); LostAdapter.notifyDataSetChanged(); return; } progress.setVisibility(View.GONE); LostAdapter.addAll(losts); listview.setAdapter(LostAdapter); } @Override public void onError(int code, String arg0) { // TODO Auto-generated method stub showErrorView(0); } }); } public void queryFounds() { showView(); BmobQuery<Found> query = new BmobQuery<Found>(); query.order("createdAt");// 按照时间降序 query.findObjects(this, new FindListener<Found>() { @Override public void onSuccess(List<Found> arg0) { // TODO Auto-generated method stub LostAdapter.clear(); FoundAdapter.clear(); if (arg0 == null || arg0.size() == 0) { showErrorView(1); FoundAdapter.notifyDataSetChanged(); return; } FoundAdapter.addAll(arg0); listview.setAdapter(FoundAdapter); progress.setVisibility(View.GONE); } @Override public void onError(int code, String arg0) { // TODO Auto-generated method stub showErrorView(1); } }); } /** * 请求出错或者无数据时候显示的界面 showErrorView * */ private void showErrorView(int tag) { progress.setVisibility(View.GONE); listview.setVisibility(View.GONE); layout_no.setVisibility(View.VISIBLE); if (tag == 0) { tv_no.setText(getResources().getText(R.string.list_no_data_lost)); } else { tv_no.setText(getResources().getText(R.string.list_no_data_found)); } } private void showView() { listview.setVisibility(View.VISIBLE); layout_no.setVisibility(View.GONE); } @Override public void onEdit(View v) { // TODO Auto-generated method stub String tag = tv_lost.getTag().toString(); Intent intent = new Intent(this, AddActivity.class); String title = ""; String describe = ""; String phone = ""; if (tag.equals("Lost")) { title = LostAdapter.getItem(position).getTitle(); describe = LostAdapter.getItem(position).getDescribe(); phone = LostAdapter.getItem(position).getPhone(); } else { title = FoundAdapter.getItem(position).getTitle(); describe = FoundAdapter.getItem(position).getDescribe(); phone = FoundAdapter.getItem(position).getPhone(); } intent.putExtra("decribe", describe); intent.putExtra("phone", phone); intent.putExtra("title", title); intent.putExtra("from", tag); startActivityForResult(intent, Constants.REQUESTCODE_ADD); } @Override public void onDelete(View v) { // TODO Auto-generated method stub String tag = tv_lost.getTag().toString(); if (tag.equals(”Lost")) { deleteLost(); } else { deleteFound(); } } private void deleteLost() { Lost lost = new Lost(); lost.setObjectId(LostAdapter.getItem(position).getObjectId()); lost.delete(this, new DeleteListener() { @Override public void onSuccess() { // TODO Auto-generated method stub LostAdapter.remove(position); } @Override public void onFailure(int code, String arg0) { // TODO Auto-generated method stub } }); } private void deleteFound() { Found found = new Found(); found.setObjectId(FoundAdapter.getItem(position).getObjectId()); found.delete(this, new DeleteListener() { @Override public void onSuccess() { // TODO Auto-generated method stub FoundAdapter.remove(position); } @Override public void onFailure(int code, String arg0) { // TODO Auto-generated method stub } }); } }