智能厨房重构-使用Bmob后端云实现朋友圈的功能
来源:互联网 发布:java compare返回结果 编辑:程序博客网 时间:2024/05/06 17:26
上一篇智能厨房重构-使用Bmob后端云实现用户注册登录的功能,初步介绍了Bmob的一些简单用法,现在我们来介绍一下稍微高级的东西,实现朋友圈的功能。上一篇我们已经实现了用户注册的功能,现在我们就要让这些用户能够分享自己制作美食的经历,增加用户的分享乐趣。
1. 服务器建表
看过上一篇博客的都应该知道了,我们要想让服务器支持上传下载查询等基本功能,都是建立在服务器已经存在对象表的基础上面的。我们先来分析一下数据结构,一个说说应该包含这些属性:
1.用户资料 这就对应我们之前建立好的用户表,设为外键即可
2.说说的文字部分 这就对应着一个String类型
3.说说的图片部分 这就对应着一个List 文件组合
分析完了之后建好的表就是这样的。
2. 客户端建立对应的对象
/** * 作者:GXL on 2016/8/3 0003 * 博客: http://blog.csdn.net/u014316462 * 作用:动态圈Item */public class DynamicItem extends BmobObject implements Serializable{ public User getWriter() { return Writer; } public void setWriter(User writer) { Writer = writer; } public User Writer; //作者描述 public String Text; //作者上传图片集合 public List<BmobFile> PhotoList; //作者描述文字 public String Detail; public String getText() { return Text; } public void setText(String text) { Text = text; } public List<BmobFile> getPhotoList() { return PhotoList; } public void setPhotoList(List<BmobFile> photoList) { PhotoList = photoList; } public String getDetail() { return Detail; } public void setDetail(String detail) { Detail = detail; }}
一条DynamicItem记录对应着User中的一条记录,通过这个属性这两个表建立联系。
注意点 Bmob上传文件组的方法,比如就上传上面一条朋友圈,一定要先将朋友圈中的图片文件都先上传上去,然后再上传成功的回调中,将上传成功的文件UrlList,设置给朋友圈对象,最后在上传朋友圈对象,相当于要经历两次上传的过程。看一下代码:
/** * 上传动态 * * @param dynamicitem */ public void sendDynamicItem(final DynamicItem dynamicitem, final FoodModelImpl.BaseListener listener) { if (dynamicitem.getPhotoList().size() != 0) { final String[] array = new String[dynamicitem.getPhotoList().size()]; for (int i = 0; i < dynamicitem.getPhotoList().size(); i++) { array[i] = dynamicitem.getPhotoList().get(i).getLocalFile().getAbsolutePath(); Log.i("path", "sendDynamicItem: " + array[i] + " " + dynamicitem.getPhotoList().size()); } BmobFile.uploadBatch(BaseApplication.getmContext(), array, new UploadBatchListener() { @Override public void onSuccess(List<BmobFile> files, List<String> urls) { if (urls.size() == array.length) { dynamicitem.setPhotoList(files); dynamicitem.save(BaseApplication.getmContext(), new SaveListener() { @Override public void onSuccess() { listener.getSuccess(null); Toast.makeText(BaseApplication.getmContext(), "上传成功", Toast.LENGTH_LONG).show(); } @Override public void onFailure(int i, String s) { Toast.makeText(BaseApplication.getmContext(), "上传失败", Toast.LENGTH_LONG).show(); listener.getFailure(); } }); } } @Override public void onError(int statuscode, String errormsg) { Log.i("TAG", "onError: " + errormsg + statuscode); } @Override public void onProgress(int curIndex, int curPercent, int total, int totalPercent) { Log.i("TAG", "onProgress: " + curIndex + " " + curPercent + " " + total); } }); } else { dynamicitem.save(BaseApplication.getmContext(), new SaveListener() { @Override public void onSuccess() { listener.getSuccess(null); Toast.makeText(BaseApplication.getmContext(), "上传成功", Toast.LENGTH_LONG).show(); } @Override public void onFailure(int i, String s) { Toast.makeText(BaseApplication.getmContext(), "上传失败", Toast.LENGTH_LONG).show(); listener.getFailure(); } }); } }
上面的代码的流程是这样的,首先两种情况:
当前用户发送的说说中,没有图片,那我们只需要直接上传DynamicItem对象即可。
如果当前用户发送的说说中,含有图片列表,我们就需要先上传图片文件,如果将DynamicItem的PhotoList设为返回的files.然后上传DynamicItem对象。
3. 实战
首先我们先来看一下效果图:
展示朋友圈的效果图
发送说说的效果图
效果还都可以吧!下面我简单介绍一下主要的功能代码,关于布局的展示都比较基础,感兴趣的兄弟,可以直接看github上面的源码哈。
DyanmicItem的Model类,负责所有的Dynamic的数据处理部分。
/** * 作者:GXL on 2016/8/3 0003 * 博客: http://blog.csdn.net/u014316462 * 作用:对朋友圈数据操作的model */public class DynamicModel implements DynamicModelImpl { /** * 获取所有的朋友圈消息 * * @param listener */ @Override public void getDynamicItem(final FoodModelImpl.BaseListener listener) { BmobQuery<DynamicItem> query = new BmobQuery<DynamicItem>(); query.order("-createdAt"); query.findObjects(BaseApplication.getmContext(), new FindListener<DynamicItem>() { @Override public void onSuccess(List<DynamicItem> object) { if (object != null && object.size() != 0) { listener.getSuccess(object); } } @Override public void onError(int code, String msg) { } }); } /** * 获取当前用户的所有动态 * * @param user * @param listener */ @Override public void getDynamicItemByPhone(User user, final FoodModelImpl.BaseListener listener) { BmobQuery<DynamicItem> query = new BmobQuery<DynamicItem>(); query.addWhereEqualTo("Writer", user); query.findObjects(BaseApplication.getmContext(), new FindListener<DynamicItem>() { @Override public void onSuccess(List<DynamicItem> object) { if (object != null && object.size() != 0) { listener.getSuccess(object); } } @Override public void onError(int code, String msg) { } }); } /** * 上传动态 * * @param dynamicitem */ public void sendDynamicItem(final DynamicItem dynamicitem, final FoodModelImpl.BaseListener listener) { if (dynamicitem.getPhotoList().size() != 0) { final String[] array = new String[dynamicitem.getPhotoList().size()]; for (int i = 0; i < dynamicitem.getPhotoList().size(); i++) { array[i] = dynamicitem.getPhotoList().get(i).getLocalFile().getAbsolutePath(); Log.i("path", "sendDynamicItem: " + array[i] + " " + dynamicitem.getPhotoList().size()); } BmobFile.uploadBatch(BaseApplication.getmContext(), array, new UploadBatchListener() { @Override public void onSuccess(List<BmobFile> files, List<String> urls) { if (urls.size() == array.length) { dynamicitem.setPhotoList(files); dynamicitem.save(BaseApplication.getmContext(), new SaveListener() { @Override public void onSuccess() { listener.getSuccess(null); Toast.makeText(BaseApplication.getmContext(), "上传成功", Toast.LENGTH_LONG).show(); } @Override public void onFailure(int i, String s) { Toast.makeText(BaseApplication.getmContext(), "上传失败", Toast.LENGTH_LONG).show(); listener.getFailure(); } }); } } @Override public void onError(int statuscode, String errormsg) { Log.i("TAG", "onError: " + errormsg + statuscode); } @Override public void onProgress(int curIndex, int curPercent, int total, int totalPercent) { Log.i("TAG", "onProgress: " + curIndex + " " + curPercent + " " + total); } }); } else { dynamicitem.save(BaseApplication.getmContext(), new SaveListener() { @Override public void onSuccess() { listener.getSuccess(null); Toast.makeText(BaseApplication.getmContext(), "上传成功", Toast.LENGTH_LONG).show(); } @Override public void onFailure(int i, String s) { Toast.makeText(BaseApplication.getmContext(), "上传失败", Toast.LENGTH_LONG).show(); listener.getFailure(); } }); } }}
所有的用途我都添加了注释,下载源码,学起来还是比较简单的。
看一下发说说的Activity,展示部分就是一个listview,如何将数据绑定到listview中没有什么好讲的了。
/** * 作者:GXL on 2016/8/3 0003 * 博客: http://blog.csdn.net/u014316462 * 作用:发朋友圈页面 */public class SendDynamicActivity extends Activity { private final int REQUEST_CODE = 0x01; @Bind(R.id.cancel) TextView cancel; @Bind(R.id.send) TextView send; @Bind(R.id.edit_content) EditText editContent; @Bind(R.id.gridView) GridView gridView; private DynamicPhotoChooseAdapter mDynamicPhotoChooseAdapter; private final String LOGINUSER = "loginuser"; private User mUser; private Dialog mLoadingDialog; private Dialog mLoadingFinishDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.senddynamic_activity_main); mUser = (User) getIntent().getSerializableExtra("User"); ButterKnife.bind(this); init(); } public void init() { final PhotoPickerIntent intent = new PhotoPickerIntent(SendDynamicActivity.this); intent.setPhotoCount(6); intent.setShowCamera(true); mDynamicPhotoChooseAdapter = new DynamicPhotoChooseAdapter(SendDynamicActivity.this); gridView.setAdapter(mDynamicPhotoChooseAdapter); gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (position == mDynamicPhotoChooseAdapter.getCount() - 1) { startActivityForResult(intent, REQUEST_CODE); } } }); mLoadingDialog = DialogBuilder.createLoadingDialog(SendDynamicActivity.this, "正在上传"); mLoadingFinishDialog = DialogBuilder.createLoadingfinishDialog(SendDynamicActivity.this, "上传完成"); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // 选择结果回调 if (requestCode == REQUEST_CODE && resultCode == RESULT_OK && data != null) { List<String> pathList = data.getStringArrayListExtra(PhotoPickerActivity.KEY_SELECTED_PHOTOS); List<DynamicPhotoItem> list = new ArrayList<>(); if (pathList.size() != 0) { for (String path : pathList ) { list.add(new DynamicPhotoItem(path, false)); } } mDynamicPhotoChooseAdapter.addData(list); } } @OnClick({R.id.cancel, R.id.send}) public void onClick(View view) { switch (view.getId()) { case R.id.cancel: finish(); break; case R.id.send: mLoadingDialog.show(); DynamicItem dynamicItem = new DynamicItem(); dynamicItem.setWriter(mUser); List<BmobFile> fileList = new ArrayList<>(); ArrayList<DynamicPhotoItem> photoItems = (ArrayList<DynamicPhotoItem>) mDynamicPhotoChooseAdapter.getData(); for (int i = 0; i < photoItems.size() - 1; i++) { fileList.add(new BmobFile(new File(photoItems.get(i).getFilePath()))); } dynamicItem.setText(editContent.getText().toString()); dynamicItem.setPhotoList(fileList); new DynamicModel().sendDynamicItem(dynamicItem, new FoodModelImpl.BaseListener() { @Override public void getSuccess(Object o) { mLoadingDialog.dismiss(); mLoadingFinishDialog.show(); new Handler().postDelayed(new Runnable() { @Override public void run() { mLoadingFinishDialog.dismiss(); finish(); } }, 500); } @Override public void getFailure() { } }); break; } }}
关于获取本地手机的图片文件,还使用了一个ImageSelector框架,使用起来特别简单方便,可以让你更加专注与自身的核心功能,使用方法,在buildgradle中添加下面这行代码建立依赖。
compile 'me.iwf.photopicker:PhotoPicker:0.1.8'
初始化
final PhotoPickerIntent intent = new PhotoPickerIntent(SendDynamicActivity.this); intent.setPhotoCount(6);//最多选择图片的个数 intent.setShowCamera(true);//是否显示相机拍照
调用
startActivityForResult(intent, REQUEST_CODE);
获取返回的文件地址list
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // 选择结果回调 if (requestCode == REQUEST_CODE && resultCode == RESULT_OK && data != null) { List<String> pathList = data.getStringArrayListExtra(PhotoPickerActivity.KEY_SELECTED_PHOTOS); } }
实现朋友圈功能的核心代码和步骤基本都在上面了,因为自己水平问题可能讲解有点贴代码了,但是基本的思想就是如此,大家多看一遍必定可以理解,下一篇我们将介绍一个使用vitamio打造属于自己的美食视频教学功能。
详细的项目代码地址:https://github.com/gxl1240779189/ReIntelligentKitchen
- 智能厨房重构-使用Bmob后端云实现朋友圈的功能
- 智能厨房重构-使用Bmob后端云实现用户注册登录的功能。
- 智能厨房重构-使用Bmob后端云实现用户注册登录的功能。
- 智能厨房重构-使用vitamio实现视频播放功能
- 智能厨房重构-用ActiveAndroid来实现收藏的功能
- Bmob后端云的使用
- Bmob后端云的使用(1)——入门指导及实现登录注册功能
- 使用Bmob后端云遇到的坑
- Bmob后端云的集成与使用
- Bmob后端云的基本使用
- 基于Bmob后端云实现APP,登录功能--binbinyang
- Bmob 后端云——史上最简单的注册功能
- Bmob后端云使用心得
- 智能厨房重构-项目分包
- 智能厨房重构-MVP架构
- 通过Bmob云后端来实现一个完整的app
- 小白入门---BMOB后端云的使用
- 使用Unity连接Bmob后端云
- python学习笔记-python安装
- LightOJ 1058 Parallelogram Counting【平行四边形的判定】
- FreeSwitch 终端命令详细介绍
- hdu 5834 Magic boy Bi Luo with his excited tree (树形dp)
- 可视化网络安全技术“看透”黑客
- 智能厨房重构-使用Bmob后端云实现朋友圈的功能
- Working with the DOM
- OpenCV中的肤色检测
- 函数指针&指针函数
- Codeforces Round #328 (Div. 2) A(模拟) B(数学) C(数学)
- HDU1698 Just a Hook [lazy+成段更新]
- 导入Maven项目后,Eclipse提示“Missing artifact ”类的错误
- 省市区三级联动
- 【深入理解java集合系列】List,Set,Map用法以及区别