我的onCreate方法有问题。我已经确定,当我切换到这个活动时,onCreate方法被调用两次,因此启动2个我不想要的线程。因为线程将坐标发送到RaspberryPi,而第二个不需要的线程总是发送0 0 0,我不想要。我似乎无法找到解决这个问题的方法。 。 。如果有人可以告诉我一个修复程序,那么我会很感激帮助,所以线程只启动一次。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Joystick = (ImageView) findViewById(R.id.Joystick);
Regler = (ImageView) findViewById(R.id.Regler);
buttonFoto = (Button) findViewById(R.id.buttonFoto);
buttonVideo = (Button) findViewById(R.id.buttonVideo);
buttonNeu = (Button) findViewById(R.id.buttonNeu);
buttonSpeichern = (Button) findViewById(R.id.buttonSpeichern);
touchscreenJoystick = (TextView) findViewById(R.id.touchscreenJoystick);
touchscreenJoystick.setOnTouchListener(this);
touchscreenRegler = (TextView) findViewById(R.id.touchscreenRegler);
touchscreenRegler.setOnTouchListener(this);
RL = (RelativeLayout) findViewById(R.id.activity_main);
running = true;
firstTouch = true;
Bild = (WebView) findViewById(R.id.webView);
Bild.loadUrl("http://10.0.0.1:8080/stream");
thread = new Thread(new MainActivity.TransmitThread());
thread.start();
}
修改 我尝试使用SaveInstanceState
//Same onCreate-stuff as above
if(savedInstanceState == null)
{
thread = new Thread(new MainActivity.TransmitThread());
thread.start();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("message","crashed");
super.onSaveInstanceState(outState);
}
这样做有点奇怪。现在我只有一个线程在发送一次坐标后立即崩溃。
日志:
我发送之前发送的Log.i:
I/sent: //X: 0 //Y: 0 //Z: 0
之后的日志
I/System: core_booster, getBoosterConfig = false
编辑2:
我也试过在另一个时间启动线程。在我的onTouch中这样:
public boolean onTouch(View v, MotionEvent me)
{
xt = me.getX();
yt = me.getY();
int Aktion = me.getAction();
if(firstTouch)
{
thread = new Thread(new MainActivity.TransmitThread());
thread.start();
firstTouch = false;
}
//other stuff that i need to do here
}
但是这与我尝试使用SaveInstanceState相同,这是一个传输一次但没有循环的线程。
编辑3: 我应该发布我的帖子
class TransmitThread implements Runnable
{
@Override
public void run()
{
while(running)
{
delay();
xss = xs;
yss = ys;
zss = zs;
Log.i("sent","//X: " + xss + " //Y: " + yss + " //Z: " + zss);
transmit();
}
}
public void transmit()
{
try{
socket = new Socket(ServerIP,ServerPort);
OutputStream outputStream = socket.getOutputStream();
PrintStream printStream = new PrintStream(outputStream);
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
printStream.print(xs + " " + ys + " " + zs);
Akkustand = input.readLine();
handler.sendEmptyMessage(0);
}catch(UnknownHostException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
public void delay(){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
最终编辑:
我设法做了一个解决方法。我在发送之前检查如果值为0,如果是,那么我将其更改为200.在另一端,我检查它是否为200并将其更改为0并忽略我得到的任何0。
答案 0 :(得分:0)
首先,OnCreate只会在Activity的每个生命周期中被调用一次。但是,有许多情况会导致您的活动被杀死并恢复生机。因此,OnCreate再次被调用。
首先,您可以调试代码并找到重复调用的位置。
注意:为了避免这种情况,您可以将状态信息保存在onSaveInstanceState中,并将其恢复到您在创建时获得的状态包中。
由于
答案 1 :(得分:0)
OnCreate()已经创建了一个主线程,然后通过手动创建主类的线程来调用主类的另一个实例。
答案 2 :(得分:0)
根据this回答所有你不需要布尔检查,只需检查savedInstance是否为null,然后才启动第二个线程。
更通用的解决方案是初始化并启动onStart()
中的线程,但不要忘记在onStop()
中停止它。如果你想让这个线程在后台长时间运行 - 我建议你开始使用其他东西 - Service docs
答案 3 :(得分:0)
任何配置更改都会导致Android重新启动您的Activity,如屏幕旋转,键盘可用性等。系统实际执行的操作是调用onDestroy()
然后立即调用onCreate()
,这意味着原始的Activity对象在没有任何执行后台线程知识的情况下被新的替换,因此只有启动线程的Activity对象知道线程已经启动。
处理此问题的更好方法是在活动中保留线程。
Activity类包含两种处理线程保留的方法:
public Object onRetainNonConfigurationInstance()
在配置更改发生之前调用
public Object getLastNonConfigurationInstance()
在新的Activity对象中调用以检索onRetainNonConfigurationInstance()
所以你可以通过以下方式实现这一点。
private static MyThread t;
@Override
public void onCreate(Bundle savedInstanceState) {
Object retainedObject = getLastNonConfigurationInstance();
if (retainedObject != null) {
t = (MyThread) retainedObject;
}
else{
t = new MyThread();
t.start();
}
}
@Override
public Object onRetainNonConfigurationInstance() {
if (t != null && t.isAlive()) {
return t;
}
return null;
}