基于Bmob数据服务实现的简单群聊

logo

  • 简介
  • 运行效果
  • 设计思路
  • 代码
  • 参考

一、简介

该应用主要利用bmob提供的 数据实时同步 功能来让客户端对云端指定表的监听完成了群聊的基本功能,同时在消息类型上区分了文本消息和图片消息。应用可以判断消息类型并根据对应的消息类型来显示文本/图片。笔者接触Android不久,在性能的优化及程序的设计上如有不足还望指出~ 谢谢~

二、运行效果

群聊消息截图

三、设计思路

即时通讯的实现最大的难点在于双方数据的实时同步,现在Bmob已经帮我们解决了,所以我们只需要将云端的数据加载到ListView中进行显示即可。

我们要实现两种消息:文本消息 和 图片消息。两种消息在云端存放的本质是相同的,只不过一个存放的内容为发送的消息文本一个存放的是云端图片的URL。两种消息的区分可以另外定义一个变量viewtype(准确来说应该命名msgtype,命名viewtype是因为对应了不同的viewholder,不过这都不重要,不要在意这些细节)来实现,当viewtype为0时,以文本的形式展示,当viewtype为1时,以图片的形式展示。

我设计了如下结构:

类型变量名
Stringname
Stringcontent
intviewtype

其中name可省,也可以根据自己的需要添加其它值

之后调用bmob提供的save方法即可完成数据的保存,在BmobRealTimeData类的回调函数中就可以拿到新增的数据了。

本地数据的加载方法主要参考了文章结尾的 参考 ,在原基础上做了一些调整。

四、代码

除了以下代码使用前还要进行 Bmob的初始化 以及在 清单中添加相应的权限build.gradle中的部分依赖

Chat.class

public class Chat extends BmobObject{

    public final static int TEXT_TYPE = 0;
    public final static int IMAGE_TYPE = 1;

    private int viewtype;
    private String name;
    private String content;

    public Chat(String name, String content, int type) {
        this.name = name;
        this.content = content;
        this.viewtype = type;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setViewtype(int viewtype) {
        this.viewtype = viewtype;
    }

    public int getViewtype() {
        return viewtype;
    }
}

MainActivity.class

public class MainActivity extends Activity implements View.OnClickListener {

    ListView mListView;
    String name;
    Button btn_send, btn_pic_send;
    EditText et_content;

    PlayAdapter mPlayAdapter;
    List messages = new ArrayList();
    BmobRealTimeData data = new BmobRealTimeData();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        name = telephonyManager.getDeviceId().toString();

        initview();
        initdata();

    }

    private void initdata() {


        BmobQuery query = new BmobQuery();
        query.order("createdAt");
        query.setLimit(500);
        query.findObjects(new FindListener() {
            @Override
            public void done(List list, BmobException e) {
                if (e == null) {
                    for (Chat chat : list) {
                        messages.add(chat);
                    }
                } else {
                    Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
                }
            }
        });

        data.start(new ValueEventListener() {
            @Override
            public void onConnectCompleted(Exception e) {
                if (data.isConnected()) {
                    data.subTableUpdate("Chat");
                }
            }

            @Override
            public void onDataChange(JSONObject jsonObject) {
                if (BmobRealTimeData.ACTION_UPDATETABLE.equals(jsonObject.optString("action"))) {
                    JSONObject data = jsonObject.optJSONObject("data");

                    Chat chat = new Chat(data.optString("name"), data.optString("content"), Integer.parseInt(data.optString("viewtype")));
                    messages.add(chat);

                    mPlayAdapter.notifyDataSetChanged();
                }
            }
        });
    }

    private void initview() {
        mListView = (ListView) findViewById(R.id.lv_data);
        mPlayAdapter = new PlayAdapter(MainActivity.this, messages, name);
        mListView.setAdapter(mPlayAdapter);
        mListView.setDivider(null);
        mListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

        btn_pic_send = (Button) findViewById(R.id.btn_send_pic);
        btn_send = (Button) findViewById(R.id.btn_send);
        btn_pic_send.setOnClickListener(this);
        btn_send.setOnClickListener(this);
        et_content = (EditText) findViewById(R.id.et_msg);
    }

    private void sendMsg(String name, String msg, int msgType){
        Chat chat = new Chat(name, msg, msgType);
        chat.save(new SaveListener() {
            @Override
            public void done(String s, BmobException e) {
                if (e == null) {
                    et_content.setText("");
                }
            }
        });
    }

    @Override
    public void onClick(View view) {
        if (view == btn_send) {
            String content = et_content.getText().toString();
            if (TextUtils.isEmpty(name) || TextUtils.isEmpty(content)) {
                Toast.makeText(MainActivity.this, "消息不能为空", Toast.LENGTH_SHORT).show();
                return;
            } else {
                sendMsg(name, content, Chat.TEXT_TYPE);
            }
        } else if (view == btn_pic_send) {
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.setType("image/*");
            startActivityForResult(intent, 42);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 42) {
            try {
                Uri uri = data.getData();
                String path = getPath(this, uri);
                final BmobFile pic = new BmobFile(new File(path));
                pic.uploadblock(new UploadFileListener() {
                    @Override
                    public void done(BmobException e) {
                        if (e == null) {
                            sendMsg(name, pic.getFileUrl(), Chat.IMAGE_TYPE);
                        }
                    }
                });
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getPath(Context context, Uri uri) throws URISyntaxException {
        if ("content".equalsIgnoreCase(uri.getScheme())) {
            String[] projection = { "_data" };
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver().query(uri, projection, null, null, null);
                int column_index = cursor.getColumnIndexOrThrow("_data");
                if (cursor.moveToFirst()) {
                    return cursor.getString(column_index);
                }
            } catch (Exception e) {
                // Eat it  Or Log it.
            }
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }
}

MsgAdapter.class

public class MsgAdapter extends BaseAdapter {

    public static final int ITEM_TEXT = 0;
    public static final int ITEM_PIC = 1;

    private List mList;
    private Context context;
    private String MyName;
    private LayoutInflater inflater;

    class Hodler1 {
        LinearLayout leftLayout;
        LinearLayout rightLayout;
        TextView leftMsg;
        TextView rightMsg;

        Hodler1(View view) {
            leftLayout = view.findViewById(R.id.left_layout);
            rightLayout = view.findViewById(R.id.right_layout);
            leftMsg = view.findViewById(R.id.left_msg);
            rightMsg = view.findViewById(R.id.right_msg);
        }
    }

    class Hodler2 {
        LinearLayout left_pic_layout;
        LinearLayout right_pic_layout;
        ImageView leftPic;
        ImageView rightPic;

        Hodler2(View view) {
            left_pic_layout = view.findViewById(R.id.pic_left_layout);
            right_pic_layout = view.findViewById(R.id.pic_right_layout);
            leftPic = view.findViewById(R.id.iv_picture_left);
            rightPic = view.findViewById(R.id.iv_picture_right);
        }
    }

    public PlayAdapter(Context context, List mList, String name) {
        this.context = context;
        this.mList = mList;
        inflater = LayoutInflater.from(context);
        this.MyName = name;
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public Object getItem(int i) {
        return mList.get(i);
    }

    @Override
    public int getItemViewType(int position) {
        return mList.get(position).getViewtype();
    }

    //图片与文本对应两种不同的viewholder
    @Override
    public int getViewTypeCount() {
        return 2;
    }

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

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        int type = getItemViewType(i);

        Hodler1 hodler1 = null;
        Hodler2 hodler2 = null;

        if (view == null) {

            switch (type) {
                case ITEM_TEXT:
                    view = inflater.inflate(R.layout.msg_item, null);
                    hodler1 = new Hodler1(view);

                    if (mList.get(i).getName().equals(MyName)) {
                        hodler1.leftLayout.setVisibility(View.GONE);
                        hodler1.rightLayout.setVisibility(View.VISIBLE);
                        hodler1.rightMsg.setText(mList.get(i).getContent());
                    } else {
                        hodler1.leftLayout.setVisibility(View.VISIBLE);
                        hodler1.leftMsg.setText(mList.get(i).getContent());
                        hodler1.rightLayout.setVisibility(View.GONE);
                    }
                    view.setTag(hodler1);
                    break;
                case ITEM_PIC:
                    view = inflater.inflate(R.layout.msg_item_pic, null);
                    hodler2 = new Hodler2(view);

                    if (mList.get(i).getName().equals(MyName)) {
                        hodler2.left_pic_layout.setVisibility(View.GONE);
                        hodler2.right_pic_layout.setVisibility(View.VISIBLE);
                        Picasso.with(context).load(mList.get(i).getContent()).into(hodler2.rightPic);
                    } else {
                        hodler2.left_pic_layout.setVisibility(View.VISIBLE);
                        hodler2.right_pic_layout.setVisibility(View.GONE);
                        Picasso.with(context).load(mList.get(i).getContent()).into(hodler2.leftPic);
                    }
                    view.setTag(hodler2);
                    break;
                default:
                    break;
            }
        } else {
            switch (type) {
                case ITEM_TEXT:
                    hodler1 = (Hodler1) view.getTag();
                    if (mList.get(i).getName().equals(MyName)) {
                        hodler1.leftLayout.setVisibility(View.GONE);
                        hodler1.rightLayout.setVisibility(View.VISIBLE);
                        hodler1.rightMsg.setText(mList.get(i).getContent());
                    } else {
                        hodler1.leftLayout.setVisibility(View.VISIBLE);
                        hodler1.leftMsg.setText(mList.get(i).getContent());
                        hodler1.rightLayout.setVisibility(View.GONE);
                    }
                    break;
                case ITEM_PIC:
                    hodler2 = (Hodler2) view.getTag();
                    if (mList.get(i).getName().equals(MyName)) {
                        hodler2.left_pic_layout.setVisibility(View.GONE);
                        hodler2.right_pic_layout.setVisibility(View.VISIBLE);
                        Picasso.with(context).load(mList.get(i).getContent()).into(hodler2.rightPic);
                    } else {
                        hodler2.left_pic_layout.setVisibility(View.VISIBLE);
                        hodler2.right_pic_layout.setVisibility(View.GONE);
                        Picasso.with(context).load(mList.get(i).getContent()).into(hodler2.leftPic);
                    }
                    break;
                default:
                    break;
            }
        }
        return view;
    }
}

五、参考

简书责编内容来自:简书 (源链) | 更多关于

阅读提示:酷辣虫无法对本内容的真实性提供任何保证,请自行验证并承担相关的风险与后果!
本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 移动开发 » 基于Bmob数据服务实现的简单群聊

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录