Android中Thread.start()无法解析符号问题及类调用咨询
问题解答
1. 出现"cannot resolve symbol 'start'"错误的原因
- 类定义语法错误:你写的
public class ExecThread(String id)完全不符合Java语法,正确的类定义应该是public class ExecThread,构造方法才是public ExecThread(String id),你把类声明和构造方法混在了一起。 - 代码执行位置错误:
thread.start();直接写在类的成员变量声明区域,Java不允许在类的顶级作用域直接执行方法调用这类语句,只能在构造方法、普通方法或代码块里执行。 - 额外问题:代码里还有未定义的变量(
a_string、ipAddress、port),而且子线程直接调用te.setText()操作UI,这在Android里会触发CalledFromWrongThreadException,后续也需要修正。
2. 在Fragment按钮点击事件中调用ExecThread的正确方式
先修正ExecThread类的写法,使其符合Java和Android规范,再在Fragment的按钮点击逻辑中实例化该类。
修正后的ExecThread类
package com.sample.ui.dashboard; import android.os.Handler; import android.os.Looper; import android.widget.TextView; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; public class ExecThread { private final String requestA; private final TextView textView; private final String ipAddress; private final int port; // 用于子线程切换到主线程更新UI的Handler private final Handler mainHandler = new Handler(Looper.getMainLooper()); // 正确的构造方法 public ExecThread(String id, String requestA, TextView textView, String ipAddress, int port) { this.requestA = requestA; this.textView = textView; this.ipAddress = ipAddress; this.port = port; // 在构造方法内启动轮询线程 startPolling(); } private void startPolling() { Runnable runnable = new Runnable() { String read = null; int count = 5; @Override public void run() { try { while (count != 0) { Socket socket = new Socket(ipAddress, port); socket.setKeepAlive(true); OutputStream out = socket.getOutputStream(); PrintWriter output = new PrintWriter(out, true); output.println(requestA); BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); read = input.readLine(); if (read != null && read.length() >= 250) { final String updateText = String.valueOf(count) + " - " + read.substring(4, 16); // 通过Handler切换到主线程更新UI mainHandler.post(() -> textView.setText(updateText)); } socket.close(); count--; // 24小时轮询需添加间隔延迟,示例为1秒,可根据实际调整 Thread.sleep(1000); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } } }; Thread thread = new Thread(runnable); thread.start(); } }
在Fragment中调用ExecThread
在你的Fragment的按钮点击事件里,获取必要参数后实例化ExecThread:
public class DashboardFragment extends Fragment { private TextView meterNumberTv; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_dashboard, container, false); meterNumberTv = view.findViewById(R.id.meternumber); Button pollBtn = view.findViewById(R.id.poll_button); // 替换为你实际的按钮ID pollBtn.setOnClickListener(v -> { // 替换为实际业务参数 String deviceId = "device_001"; String requestA = "your_modbus_request_content"; String ipAddress = "192.168.1.100"; int port = 502; // Modbus默认端口,按需修改 // 实例化线程类,启动硬件轮询 new ExecThread(deviceId, requestA, meterNumberTv, ipAddress, port); }); return view; } }
额外注意事项
- 24小时长期轮询建议用
ScheduledExecutorService实现定时任务,比Thread.sleep()更稳定,也方便后续停止轮询。 - 网络操作需要在
AndroidManifest.xml中添加权限:<uses-permission android:name="android.permission.INTERNET"/>。 - Fragment销毁时要停止轮询线程,避免内存泄漏,可以给ExecThread添加停止方法,在Fragment的
onDestroyView()中调用。
内容的提问来源于stack exchange,提问作者user16458899
相关产品推荐
相关产品推荐

