1

我正在尝试制作一个连接到服务器的 Android 应用程序(通过 a Socket),我相信我需要在不同的线程中完成它。但是,显然,我无法从另一个线程访问或修改 Android UI。我应该怎么办?

package me.nrubin29.quiz.student;

import android.app.Activity;
import android.widget.Toast;

import java.io.EOFException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Connection {

    private Socket socket;
    private Thread reader;
    private ObjectInputStream inputStream;
    private ObjectOutputStream outputStream;

    public void initConnection(final Activity activity, final String ip, final String port, final String name) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    Toast.makeText(activity.getApplicationContext(), "Starting connection to " + ip + ":" + Integer.parseInt(port), Toast.LENGTH_SHORT).show();

                    socket = new Socket(ip, Integer.parseInt(port));

                    Toast.makeText(activity.getApplicationContext(), "Connected!", Toast.LENGTH_SHORT).show();

                    outputStream = new ObjectOutputStream(socket.getOutputStream());

                    inputStream = new ObjectInputStream(socket.getInputStream());

                    outputStream.writeObject(name);

                    reader = new Thread(new Runnable() {
                        public void run() {
                            while (true) {
                                try {
                                    Object in = inputStream.readObject();
                                    System.out.println(in);
                                }
                                catch (EOFException e) { Toast.makeText(activity.getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); }
                                catch (Exception e) { e.printStackTrace(); }
                            }
                        }
                    });

                    reader.start();
                }
                catch (Exception e) { e.printStackTrace(); }
            }
        }).start();
    }
}
4

4 回答 4

0

在 Android 中有几种处理“多线程”的方法,您的方法可能会根据您的需要而有所不同。

假设您只使用了一个简单的 java 线程并引用了您的活动(如提供的示例),您只需调用 activity.runOnUiThread(Runnable r) 并传入将更新您的 UI 的 runnable。这实际上将 runnable 在其他 ui 事件(例如动画)之后执行。

另一个简单的处理方法是在你的 Activity 中调用“final Handler handler = new Handler()”并将这个处理程序引用传递给线程。Handler 是一个特殊的对象,它与你的 Activity 的 UI 线程绑定(当从它调用时),并且可以提供一些方法来将可运行对象从后台线程发布到 ui 线程。

另一种方法是使用 AsyncTask,这是一个简单的对象,它使您能够在处理之前在 ui 线程上执行某些操作(例如显示加载对话框),然后在后台线程上执行处理,然后执行某些操作您的主线程再次使用后台处理的结果。这条循环是 onPreExecute() -> doInBackground() -> onPostExecute()。

还有其他方法,具体取决于您的需要。

请注意以下几点:

活动具有明确定义的生命周期,它们可能(或可能不会)在您的后台处理发生之前死亡。当您尝试更新其 UI 时,您可能(或可能不需要)定义一些机制来检查活动是否仍然存在,否则您将遇到麻烦。AsyncTask 有一个非常有用的功能,可以根据您的活动 onDestroy() 接受取消,即简单地在活动 onDestroy() 上调用 AsyncTask 上的“取消”并从 AsyncTask 中检查此取消。

根据您的使用情况,后台线程可能(或可能不会)对某些内容的强引用超过它实际应该的内容。如果您要将活动中的引用传递给后台线程或 AsyncTask,我建议您查看 Java 中的 WeakReference。

根据您的平台版本,触发多个同时 AsyncTask 的线程条件可能(也可能不会)以异步或同步处理结束。

于 2013-09-23T20:10:01.170 回答
0

修改 UI 线程有很多方法,其中之一是将消息推送到处理程序。

 Handler handler = new Handler(){

  public void handleMessage( Message msg ){
     //Perform yor UI Modification
  }

}

handler.sendMessage( msg );
于 2013-09-23T20:13:25.830 回答
0

您可以使用runOnUiThread

activity.runOnUiThread(new Runnable() //run on ui thread
{
   @Override
   public void run() 
   { 
              // update ui
   }
});

http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable)

public final void runOnUiThread (Runnable action)

Added in API level 1
Runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread.

Parameters
action  the action to run on the UI thread
于 2013-09-23T19:51:42.263 回答
0

调用你传入的。这将向 UI 线程发布一条消息runOnUiThreadActivity请记住,您永远不应该向您的 UI 线程发布一条执行时间过长的消息,否则它会锁定您的应用程序并且 Android 会提示用户强制关闭它;也就是说,没有网络连接或繁重的计算。

一个例子:

activity.runOnUiThread(new Runnable()
{
    @Override
    public void run() 
    { 
          // Your UI stuff here
    }
});
于 2013-09-23T19:51:54.170 回答