【问题标题】:AndroidAsync - updating views from WebSocket.StringCallback()AndroidAsync - 从 WebSocket.StringCallback() 更新视图
【发布时间】:2015-01-26 22:22:00
【问题描述】:

我正在编写一些小型聊天应用程序,并且我正在使用 AndroidAsync 在我的应用程序中获取 WebSocket 客户端功能。所以,问题是每当我尝试从 WebSocket.StringCallback().onStringAvailable(String) 修改我的 listView 时,它都会导致异常:

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRoot.checkThread(ViewRoot.java:2932)
            at android.view.ViewRoot.focusableViewAvailable(ViewRoot.java:1712)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:452)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:452)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:452)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:452)
            at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:452)
            at android.view.View.setFlags(View.java:4614)
            at android.view.View.setFocusableInTouchMode(View.java:3190)
            at android.widget.AdapterView.checkFocus(AdapterView.java:694)
            at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:789)
            at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:31)
            at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
            at android.widget.ArrayAdapter.notifyDataSetChanged(ArrayAdapter.java:247)
            at persilabtest.zulfigarov.com.chatapp.ChatActivity$1$1.onStringAvailable(ChatActivity.java:76)
            at com.koushikdutta.async.http.WebSocketImpl$1.onMessage(WebSocketImpl.java:88)
            at com.koushikdutta.async.http.HybiParser.emitFrame(HybiParser.java:420)
            at com.koushikdutta.async.http.HybiParser.access$800(HybiParser.java:46)
            at com.koushikdutta.async.http.HybiParser$5.onDataAvailable(HybiParser.java:197)
            at com.koushikdutta.async.DataEmitterReader.handlePendingData(DataEmitterReader.java:24)
            at com.koushikdutta.async.DataEmitterReader.onDataAvailable(DataEmitterReader.java:41)
            at com.koushikdutta.async.Util.emitAllData(Util.java:22)
            at com.koushikdutta.async.AsyncNetworkSocket.onReadable(AsyncNetworkSocket.java:146)
            at com.koushikdutta.async.AsyncServer.runLoop(AsyncServer.java:788)
            at com.koushikdutta.async.AsyncServer.run(AsyncServer.java:626)
            at com.koushikdutta.async.AsyncServer.access$700(AsyncServer.java:41)
            at com.koushikdutta.async.AsyncServer$13.run(AsyncServer.java:568) 

我已经明白我不能从非 UI 线程修改视图。但我不知道在这种情况下我还能如何更新它们。这是我的 ChatActivity 代码:

public class ChatActivity extends ActionBarActivity
{
    private static final String WS_ADDRESS = "ws://192.168.0.106:8084/TestChatServer/chat";

    @InjectView(R.id.btnSend)
    Button btnSend;

    @InjectView(R.id.lvChat)
    ListView lvChat;

    @InjectView(R.id.etMsg)
    EditText etMsg;

    List<String> mMessages = new ArrayList<String>();

    ArrayAdapter<String> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);
        ButterKnife.inject(this);
        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mMessages);
        lvChat.setAdapter(adapter);

        AsyncHttpClient.getDefaultInstance()
                .websocket(WS_ADDRESS, null, new AsyncHttpClient.WebSocketConnectCallback()
                {
                    @Override
                    public void onCompleted(Exception ex, WebSocket webSocket)
                    {

                        if (ex != null)
                        {
                            ex.printStackTrace();
                            return;
                        }
                        Log.d("myLogs", "OK");

                        webSocket.setStringCallback(new WebSocket.StringCallback()
                        {
                            @Override
                            public void onStringAvailable(String s)
                            {
                                String newStr = s.replaceAll("(#+\\S+)", "<font color='#EE0000'>$1</font>");
                                Log.d("myLogs", s + "\n" + newStr);
                                mMessages.add(newStr);
                                //This line causes the exception
                                adapter.notifyDataSetChanged();
                            }
                        });
                    }
                });

    }
} 

那么,有什么想法可以在每次发送新消息时更新我的​​ listView 吗?

【问题讨论】:

标签: java android multithreading androidasync-koush


【解决方案1】:

您需要确保从 UI 线程更新视图。您可以像这样使用Activity.runOnUiThread() 来做到这一点:

runOnUiThread(new Runnable() {
     @Override
     public void run() {

     //run your code that needs to update the UI here

    }
});

这个错误Only the original thread that created a view hierarchy can touch its views 的原因是因为它检测到另一个线程(除了创建视图的线程之外)正在尝试触摸视图。如果多个资源同时尝试对某些内容进行更改,则会导致线程问题。

【讨论】:

    【解决方案2】:

    不要在没有主线程的情况下运行adapter.notifyDataSetChanged();,而是使用:

    new Handler().post(new Runnable() {
        @Override
        public void run() {
            adapter.notifyDataSetChanged()
        }
    });
    

    【讨论】:

      猜你喜欢
      • 2019-05-23
      • 2016-05-02
      • 2018-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-07
      • 1970-01-01
      相关资源
      最近更新 更多