从服务端获取朋友列表的时候遇到的坑

最近在仿写微信,需要将用户登录后的朋友列表显示出来。
基本思路是,在用户点击登录按钮后,将用户名(username)保存到intent中,然后启动活动,在活动中通过
Intent intent = getIntent();String username = intent.getStringExtra();在这里插入代码片
得到username,然后开启线程,向服务端发送请求朋友列表的包,像下面这样

// 新开线程,向服务端发送一个请求朋友列表的包
        new Thread() {
            @Override
            public void run() {
                try {
                    RequestFriendsPacket packet = new RequestFriendsPacket(username);
                    Socket socket = new Socket("10.0.2.2", 2018);
                    OutputStream out = socket.getOutputStream();
                    InputStream in = socket.getInputStream();

                    out.write(packet.serialize());
                    out.flush();

                    byte[] buffer = new byte[1024];
                    int length = in.read(buffer);
                    String friendsInThread = new String(buffer, 0, length);

                    // 通过消息机制修改主线程中的friends
                    Message message = new Message();
                    message.what = 0x0001;
                    message.obj = friendsInThread;
                    mainActHandler.sendMessage(message);

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

这样就得到了朋友列表信息(friends),然后拆解这个字符串数组得到一组朋友的名字,如下所示

String allFriends[] = friends.split("[|]");// 拆解得到本用户所有的朋友
for (int i = 0; i < allFriends.length; i++)
	Log.d("friends=====", allFriends[i]);

然后初始化RecyerView中的聊天摘要列表(chatItemList)即可。

不过这里要注意几个问题(也就是我遇到的坑,呜呜):
1、请求好友信息(friends)的线程跑的是比主线程慢的,所以原本在主线程中执行的initFragment();是要放在Handler中的,这里的Handler是处理子线程请求完成后发送给主线程的消息的,一定要在这里初始化我们的Fragment,不然会导致Fragment的聊天摘要的朋友名字缺失。我写的Handler如下:

public Handler mainActHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 0x0001) {
                friends = (String) msg.obj;
                Log.d("mainActHandler===", friends + "====");
//                fragments[0] = new WeixinFragment(friends);
                initFragment();
            }
        }
    };在这里插入代码片

2、在Fragment中获取与之关联的Activity时,最好放在方法体中而不要放在外面,因为放在外面的话有可能不会执行,如下所示:

public class WeixinFragment extends Fragment {
    private List<ChatItem> chatItemList = new ArrayList<>();

    private MainActivity mainActivity;

    private String friends = "";



    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        mainActivity = (MainActivity) getActivity();// 获取主活动

        // 得到主活动中的当前用户名,然后根据这个发送一个请求朋友列表的包给服务端,服务端根据用户名
        // 进入数据库查询都该用户的所有朋友,然后将信息(一个包含朋友列表的字符串)返回到本地即可
        Log.d("===fragmentIndex:", Integer.toString(mainActivity.getFragmentIndex()));




        friends = mainActivity.getFriends();// 这句话如果报空指针异常,将mainActivity = (MainActivity) getActivity();// 获取主活动移动到onCreateView()方法中






        Log.d("===friends:", friends);

        initChatItems();// 初始化各个聊天子项

        // 获取“微信”碎片
        LinearLayout chatItemLayout = (LinearLayout) inflater.inflate(R.layout.fragment_weixin, container, false);

        // 获取”微信“碎片中的RecyclerView,也就是聊天项目列表
        RecyclerView chatItemRecyclerView = chatItemLayout.findViewById(R.id.chat_item_recycler_view);

        // 设置分割线
//        chatItemRecyclerView.addItemDecoration(new DividerItemDecoration(mainActivity, DividerItemDecoration.VERTICAL));

        chatItemRecyclerView.addItemDecoration(new RecycleViewDivider(getContext(), LinearLayoutManager.VERTICAL));


        // 获取布局管理
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(mainActivity);
        chatItemRecyclerView.setLayoutManager(linearLayoutManager);

        ChatItemAdapter chatItemAdapter = new ChatItemAdapter(getActivity(), chatItemList);
        chatItemRecyclerView.setAdapter(chatItemAdapter);

        // 这里要注意,重新渲染的话R.layout.fragment_weixin
        // 是会被重置的,这就解释了为什么页面会加载不出来了
        // 所以直接将chatItemLayout返回就可以了
//        return inflater.inflate(R.layout.fragment_weixin, container, false);
        return chatItemLayout;
    }

3、请求好友列表信息(friends)时,向服务端写完数据一定要马上读取服务端返回的数据,不然等当前socket关掉了的话,在程序其他位置在创建socket是无法得到这个socket的,更别提获取他的数据了(小白水平有限,在这个地方卡了好久……)

发布了19 篇原创文章 · 获赞 5 · 访问量 4210

猜你喜欢

转载自blog.csdn.net/qq_41409120/article/details/84333301