【发布时间】:2018-10-01 23:42:21
【问题描述】:
我是一名大学生,正在编写一个应显示消息的 Android 应用程序,Android 设备通过 TCP 从服务器接收这些消息。
ListenForMessage 类(扩展 AsyncTask)打开 TCP 连接并在 DoInBackground 方法中从服务器接收消息。我可以在日志中打印来自服务器的消息,但是如果我尝试编辑 TextView 的文本,我的应用程序会崩溃。似乎我无法从 DoInBackground 方法编辑 TextView 的文本,尤其是不能,因为该类没有扩展创建 TextView 的活动。
我有两个活动,我在第二个活动“StreamPageMain”的 onCreate 中执行类“ListenForMessage”(在此之前,我从 MainActivity 中执行它,但这也不起作用)。我试图让该方法知道 TextView 属于哪个活动,正如您在我的代码中看到的那样,我在“ListenForMessage”类中创建了另一个方法来设置文本,因此它不是尝试更改的 DoInBackground 方法文本,但这些都不起作用。
总结: 我已经在代码中标记了那个地方,那是错误的。我需要做的是以某种方式获取名为“消息”的字符串并将该字符串放入 ID 为“textView1”的 TextView 中,这是“StreamPageMain”活动的一部分,而不是 MainActivity。
当按下按钮时,我在 MainActivity 中使用此方法:
public void stream(View V) {
EditText IPText = (EditText) findViewById(R.id.editTextBox2); //Extracting the IP from an EditTextView
EditText portText = (EditText) findViewById(R.id.editTextBox3); //Extracting the port from an EditTextView
String IP = IPText.getEditableText().toString(); //correcting the format to String
Integer port = Integer.parseInt(portText.getEditableText().toString()); //correcting the format to Integer
Intent i = new Intent(MainActivity.this, StreamPageMain.class);
i.putExtra("IP", IP);
i.putExtra("port", port);
startActivity(i);
}
第二个活动“StreamPageMain”启动。这样可行。
import android.widget.VideoView;
public class StreamPageMain extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stream_page);
Log.d("StreamingApp", "OnCreate is running.");
//In this middle part I am implementing a videostream into the second
activity, but that does not affect anything
String IP = getIntent().getStringExtra("IP");
Integer port = getIntent().getExtras().getInt("port");
ListenForMessage listenForMessage = new ListenForMessage(StreamPageMain.this, IP, port);
listenForMessage.execute();
}
}
您可以在这里看到,我是如何将 Activity StreamPageMain 传递给 ListenForMessage 类的。如果我注释掉标记的行,则类本身、连接和一切都可以正常工作:
package comn.example.ezio.streamingapp;
import android.app.Activity;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class ListenForMessage extends AsyncTask<Void, Void, Void> {
public Activity executingActivity;
public String IP;
public Integer port;
public ListenForMessage(Activity activity, String IPString, Integer portNumber) {
this.executingActivity = activity;
IP = IPString;
port = portNumber;
}
@Override
protected Void doInBackground(Void... voids) {
try (Socket socket = new Socket(IP, port)) {
Boolean connectionCancelled = false;
while (connectionCancelled == false) {
InputStreamReader isr = new InputStreamReader(socket.getInputStream());
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
Log.d("StreamingApp", "Server says: " + message);
setTextOfTextView(message); //!!!! This is it. At this line it
//crashes, no matter how I put it.
//Doing it directly here or in an
//extra method like now.
}
} catch (
UnknownHostException e)
{
e.printStackTrace();
} catch (
IOException e)
{
e.printStackTrace();
}
return null;
}
public void setTextOfTextView(String textOfTextView) {
TextView textView1 = executingActivity.findViewById(R.id.textView1);
textView1.setText("Server says: " + textOfTextView);
}
}
毕竟我对 Java 还很陌生,我的知识并没有超出我在这里发布的内容。请原谅格式错误和非最佳实践,我很高兴学习和改进!
【问题讨论】:
-
setText 操作无法在后台线程上执行。在 Async 类或 runOnUiThread 中使用 ProgressUpdate。
-
@PeterSagichnit 你成功了吗?
标签: java android android-activity android-asynctask textview