java - 如何使用 Socket.io 从另一个类正确刷新 ListView?

标签 java android listview nullpointerexception socket.io

我尝试用 android.socket.io 编写一个简单的聊天。
我下面的代码有效,但我不确定是否需要静态方法,因为对于 ListView 字段和 MyBaseAdapter 类,我收到以下消息:

Do not place Android context classes in static fields; this is a memory leak

如果我将其更改为非静态,我会收到以下错误消息:

MyBaseAdapter.notifyDataSetChanged()' on a null object reference

下面是我的代码:

package com.example.seadog.fb_dialog;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

import io.socket.emitter.Emitter;

public class MainActivity extends Activity implements Emitter.Listener {

    private static ArrayList arrayList = new ArrayList();

    private static ListView listView;
    private static MyBaseAdapter adapter;

    private TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        SocketIo socketIo = new SocketIo(this);

        if(socketIo.getSocket()==null) {
            socketIo.Connection();
        }

        listView = (ListView) findViewById(R.id.listView);
        adapter = new MyBaseAdapter(this, arrayList);
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                Intent newActivity = new Intent(MainActivity.this, Conversation.class);
                startActivity(newActivity);

            }
        });

    }

    @Override
    public void call(Object... args) {

        adapter.notifyDataSetChanged();

    }

}

下面是我的 SocketIo 类代码:

package com.example.seadog.fb_dialog;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.net.URISyntaxException;

import io.socket.client.Ack;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

public class SocketIo {

    private static Socket mSocket = null;
    private Emitter.Listener messageListener;

    private String API_BASE_URL = "http://10.0.2.2:3030";

    private Integer id = 654864;     // Website ID
    private Integer userId = 6522;   // UserID

    private String jwt;

    public SocketIo(Emitter.Listener messageListener) {
        this.messageListener = messageListener;
    }

    public void Connection() {

        try {
            mSocket = IO.socket(API_BASE_URL);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        mSocket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {

            /*
             * Join to default a room after connect
             */

            @Override
            public void call(Object... args) {

                // create json object and join to room (Website ID)
                // ...more code, not important here

            }

        }).on("jwt", new Emitter.Listener() {

            /*
             * Get a token and find all active conversations
             */

            @Override
            public void call(Object... args) {

                // get a token as args
                jwt = args[0].toString();

                JSONObject jsonObject = new JSONObject();

                try {
                    jsonObject.put("token", jwt);
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                // find active conversations
                mSocket.emit("messages::find", jsonObject, new Ack() {
                    @Override
                    public void call(Object... args) {

                        String response = args[args.length - 1].toString();

                        try {

                            JSONArray jsonArray = new JSONArray(response);

                            for (int i = jsonArray.length() - 1; i >= 0; i--) {

                                // create JSON object and add to arrayList

                                mainActivity.setArrayList(ld);

                            }

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }

                    }
                });

            }

        }).on("message", new Emitter.Listener() {

            /*
             * Message Listener
             */

            @Override
            public void call(Object... args) {

                String message = null;

                try {
                    JSONObject object = (JSONObject) args[0];

                    // Create here JSON Object and add to JSON Array

                    mainActivity.setArrayList(ld);

                } catch (JSONException e) {
                    e.printStackTrace();
                }

                String finalMessage = message;

                //mainActivity.notifyDataSetChanged();

            }

        }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {

            @Override
            public void call(Object... args) {
            }

        });

        mSocket.connect();

    }

    public Integer getId(){
        return id;
    }

    public Socket getSocket(){
        return mSocket;
    }

}

最佳答案

将您的代码分解为 MVP 模式。 编写一个与您的 Activity 直接相关的 Presenter。 Presenter 用于包装对 I/O、数据库等所需的库、框架等的调用。

演示者可以填充界面

void onData(ListData data);

不要直接调用您的 Activity ,而是调用您的演示者。他将缓存您的数据,根据您的 Activity 需要对其进行转换,并且我们的 Activity 可能有一个功能,通过类似的接口(interface)公开

void displayListItems(List<ListDataViewModel> viewModels);

如果 Activity/Presenter 将关闭,请尝试实现一个存储库,即将数据存储到本地数据库,以便您可以恢复它们。

关于java - 如何使用 Socket.io 从另一个类正确刷新 ListView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44160222/

相关文章:

java - 使用对话框将结果集导出到 java 中的文本文件

java - 获取 TweetTimelineListAdapter 的数据

java - 如何使用okhttp上传文件?

android - 带有可点击链接的 ListView 的项目不可点击

导入类时Java运行代码

java - 使用 main 方法作为启动是否合适?

java - 用于字符加密的字符

android - NavigationView headerlayout 不滚动

c# - 更改链接到 ListView 中所选项目的文本框中的值后,数据库中的表未更新

java - Json 不显示 url 数据