智能厨房重构-使用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();                }            });        }    }

上面的代码的流程是这样的,首先两种情况:

  1. 当前用户发送的说说中,没有图片,那我们只需要直接上传DynamicItem对象即可。

  2. 如果当前用户发送的说说中,含有图片列表,我们就需要先上传图片文件,如果将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

3 0