从 Socket.IO 线程中更新视图
Updating View from within a Socket.IO thread
我想是时候向我的 stackoverbros 提问了。我正在使用 socket.io-client.java https://github.com/nkzawa/socket.io-client.java 使用 socket.io 与我的节点服务器通信。到目前为止,连接工作正常。
这是 onCreate 和变量定义。
class Text
{
String username;
String message;
}
Socket socket;
ListView listView;
ArrayList<Text> texts = new ArrayList<Text>();
String username = "";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
initList();
activateEnter();
try {
startSocket();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
这是创建套接字的函数。
private void startSocket() throws URISyntaxException
{
socket = IO.socket("http://localhost");
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener()
{
@Override
public void call(Object... args)
{
socket.emit("adduser", "");
}
}).on("chat_msg", new Emitter.Listener()
{
@Override
public void call(Object... args)
{
JSONObject obj = (JSONObject)args[0];
try {
String uname = obj.getString("username");
String msg = obj.getString("msg");
updateList(uname, msg);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).on("username", new Emitter.Listener()
{
@Override
public void call(Object... args)
{
JSONObject obj = (JSONObject)args[0];
try {
username = obj.getString("username");
} catch (JSONException e) {
e.printStackTrace();
}
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener()
{
@Override
public void call(Object... args)
{
}
});
socket.connect();
}
现在,我有一个聊天功能,聊天消息通过我在套接字功能之外创建的自定义适配器进入 ListView,就像这样。
class FancyAdapter extends ArrayAdapter<Text>
{
FancyAdapter()
{
super(MainActivity.this, android.R.layout.simple_list_item_1, texts);
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if(convertView == null)
{
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.text, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.populateFrom(texts.get(position));
return(convertView);
}
}
class ViewHolder
{
public TextView text_username = null;
public TextView text_message = null;
ViewHolder(View row)
{
text_username = (TextView) row.findViewById(R.id.text_username);
text_message = (TextView) row.findViewById(R.id.text_message);
}
void populateFrom(Text w)
{
text_username.setText(w.username);
text_message.setText(w.message);
}
}
FancyAdapter adapter = null;
private void initList()
{
adapter = new FancyAdapter();
listView.setAdapter(adapter);
}
private void updateList(String uname, String message)
{
Text text = new Text();
text.username = uname;
text.message = message;
texts.add(text);
adapter.notifyDataSetChanged();
}
现在,当我从套接字调用中调用 updateList(string, string) 时,特别是 "chat_message",我得到 "ViewRootImpl$CalledFromWrongThreadException Only the original thread that created a view hierarchy can touch its views."
哦,好吧,我尝试将 list/adapter 相关函数和 类 移动到套接字函数的 EVENT_CONNECT 事件中,但似乎无法定义其中定义的内容对于其他事件,例如 "chat_message"。
所以我不确定该怎么做。
您只能与来自 UI 线程的视图进行交互试试这个:
MyActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
updateList(uname, msg);
}
});
我想是时候向我的 stackoverbros 提问了。我正在使用 socket.io-client.java https://github.com/nkzawa/socket.io-client.java 使用 socket.io 与我的节点服务器通信。到目前为止,连接工作正常。
这是 onCreate 和变量定义。
class Text
{
String username;
String message;
}
Socket socket;
ListView listView;
ArrayList<Text> texts = new ArrayList<Text>();
String username = "";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
initList();
activateEnter();
try {
startSocket();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
这是创建套接字的函数。
private void startSocket() throws URISyntaxException
{
socket = IO.socket("http://localhost");
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener()
{
@Override
public void call(Object... args)
{
socket.emit("adduser", "");
}
}).on("chat_msg", new Emitter.Listener()
{
@Override
public void call(Object... args)
{
JSONObject obj = (JSONObject)args[0];
try {
String uname = obj.getString("username");
String msg = obj.getString("msg");
updateList(uname, msg);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).on("username", new Emitter.Listener()
{
@Override
public void call(Object... args)
{
JSONObject obj = (JSONObject)args[0];
try {
username = obj.getString("username");
} catch (JSONException e) {
e.printStackTrace();
}
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener()
{
@Override
public void call(Object... args)
{
}
});
socket.connect();
}
现在,我有一个聊天功能,聊天消息通过我在套接字功能之外创建的自定义适配器进入 ListView,就像这样。
class FancyAdapter extends ArrayAdapter<Text>
{
FancyAdapter()
{
super(MainActivity.this, android.R.layout.simple_list_item_1, texts);
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
if(convertView == null)
{
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.text, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.populateFrom(texts.get(position));
return(convertView);
}
}
class ViewHolder
{
public TextView text_username = null;
public TextView text_message = null;
ViewHolder(View row)
{
text_username = (TextView) row.findViewById(R.id.text_username);
text_message = (TextView) row.findViewById(R.id.text_message);
}
void populateFrom(Text w)
{
text_username.setText(w.username);
text_message.setText(w.message);
}
}
FancyAdapter adapter = null;
private void initList()
{
adapter = new FancyAdapter();
listView.setAdapter(adapter);
}
private void updateList(String uname, String message)
{
Text text = new Text();
text.username = uname;
text.message = message;
texts.add(text);
adapter.notifyDataSetChanged();
}
现在,当我从套接字调用中调用 updateList(string, string) 时,特别是 "chat_message",我得到 "ViewRootImpl$CalledFromWrongThreadException Only the original thread that created a view hierarchy can touch its views."
哦,好吧,我尝试将 list/adapter 相关函数和 类 移动到套接字函数的 EVENT_CONNECT 事件中,但似乎无法定义其中定义的内容对于其他事件,例如 "chat_message"。
所以我不确定该怎么做。
您只能与来自 UI 线程的视图进行交互试试这个:
MyActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
updateList(uname, msg);
}
});