Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/371.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程启动两次_Java_Android - Fatal编程技术网

Java 线程启动两次

Java 线程启动两次,java,android,Java,Android,我的onCreate方法有问题。我发现,当我切换到这个活动时,onCreate方法会被调用两次,因此会启动两个我不想要的线程。因为线程向RaspberryPi发送坐标,第二个不需要的线程总是发送0,这是我不想要的。我似乎找不到解决办法,所以。如果有人能告诉我一个修复方法,使线程只启动一次,我将不胜感激 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(save

我的onCreate方法有问题。我发现,当我切换到这个活动时,onCreate方法会被调用两次,因此会启动两个我不想要的线程。因为线程向RaspberryPi发送坐标,第二个不需要的线程总是发送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);
}
这很奇怪。现在我只有一个线程在发送坐标一次后立即崩溃

日志:

日志。我在发送前放置的日志:

I/sent: //X: 0 //Y: 0 //Z: 0
紧随其后的日志

I/System: core_booster, getBoosterConfig = false
编辑2:

我还尝试过在其他时间启动线程。在我的头脑中,就像这样:

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。

首先,对于活动的每个生命周期,OnCreate只调用一次。但是,有许多情况会导致您的活动停止并恢复正常。因此,再次调用OnCreate

首先,您可以调试代码并找到它重复调用的位置

注意:为了避免这种情况,您可以将状态信息保存在onSaveInstanceState中,并将其恢复到创建时进入的状态包中


谢谢

首先,对于活动的每个生命周期,OnCreate只调用一次。但是,有许多情况会导致您的活动停止并恢复正常。因此,再次调用OnCreate

首先,您可以调试代码并找到它重复调用的位置

注意:为了避免这种情况,您可以将状态信息保存在onSaveInstanceState中,并将其恢复到创建时进入的状态包中

感谢

OnCreate()已经创建了一个主线程,然后您可以通过手动创建主类的线程来调用主类的另一个实例。

OnCreate()已经创建了一个主线程,然后通过手动创建主类的线程调用主类的另一个实例。

根据answer all,不需要布尔检查,只需检查savedInstance是否为null,然后启动第二个线程

更通用的解决方案是在
onStart()
中初始化并启动线程,但不要忘记在
onStop()中停止线程。如果你想让这个线程在后台长时间运行-我建议开始使用其他线程-

根据回答所有你不需要的布尔检查,只需检查savedInstance是否为null,然后再启动第二个线程


更通用的解决方案是在
onStart()
中初始化并启动线程,但不要忘记在
onStop()中停止线程。如果你想让这个线程在后台长时间运行-我建议你开始使用其他东西-

任何配置更改都会导致Android重新启动你的活动,比如屏幕旋转、键盘可用性等。系统实际上在做的是调用
onDestroy()
,然后立即调用
onCreate()
,这意味着原始的活动对象将被一个新的对象替换,而不知道正在执行的后台线程,因此只有启动线程的活动对象才知道该线程已启动

更好的处理方法是在活动中保留线程。

Activity类包含两种处理线程保留的方法:

public Object onRetainNonConfigurationInstance()
在配置更改发生之前调用

public Object getLastNonConfigurationInstance()
在新活动对象中调用,以检索在
onRetainonConfiguration Instance()中返回的保留对象

因此,您可以通过以下方式实现这一点

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;
    }

任何配置更改都会导致Android重新启动您的活动,如屏幕旋转、键盘可用性等。系统实际执行的操作是调用
onDestroy()
,然后立即调用
onCreate()
,这意味着原始的活动对象将被一个新的对象替换,而不知道正在执行的后台线程,因此只有启动线程的活动对象才知道该线程已启动

更好的处理方法是在活动中保留线程。

Activity类包含两种处理线程保留的方法:

public Object onRetainNonConfigurationInstance()
在配置更改发生之前调用

public Object getLastNonConfigurationInstance()
在新活动对象中调用,以检索在
onRetainonConfiguration Instance()中返回的保留对象

因此,您可以通过以下方式实现这一点

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;
    }

使用布尔值flag@Slimestone尝试调试代码并找到它。很简单。您甚至可以检查该变量是否包含0,并在发送之前避免该变量。您最终可以使用
thread.isAlive()
,但必须检查
thread!=null
启动时使用易失性字段。启动前请检查布尔标记使用布尔值flag@Slimestone尝试调试代码并找到它。很简单。您甚至可以检查该变量是否包含0,并在发送之前避免该变量。您最终可以使用
thread.isAlive()
,但必须检查
thread!=null
启动时使用易失性字段。启动前请检查布尔标记您错了-onCreate应该调用一次,但在其中创建线程使其再次被调用-好的,我同意您的消息。我只是告诉你活动的生命周期。我们可以称之为相同的