简体   繁体   中英

How do I observe a result from FutureTask in ViewModel?

Please help~ I want to observe a result from FutureTask in ViewModel. When I ran it, I found that it sleeps for 5 seconds but I still can't get the answer. I confirmed in debug mode that it is executing longJob(), and the answer is 3. But I still can't get the answer 3. The answer alwalys is [No answer].

My code is as follows

MainActivity.java

// MainActivity.java
package com.weberhwang.testlivedata;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import com.weberhwang.testlivedata.databinding.ActivityMainBinding;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;
    private MyViewModel myViewModel;
    private TextView result;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        result = binding.result; 
        result.setText("No answer");

        SummaryLiveData summaryLiveData = new SummaryLiveData();
        summaryLiveData.setB(2);

        SummaryCallable summaryCallable = new SummaryCallable();
        summaryCallable.setSummaryLiveData(summaryLiveData);

        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
        myViewModel.setSummaryCallable(summaryCallable);

        try {
            myViewModel.getAnswer().observe(this, new Observer<SummaryLiveData>() {
                @Override
                public void onChanged(SummaryLiveData s) {
            result.setText(String.valueOf(s.getAnswer()));
                }
            });
        } catch (Exception e) {
            Log.d("MyLog", e.getMessage());
        }
    }
}

MyViewModel.java

MyViewMode.java
package com.weberhwang.testlivedata;

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import java.util.concurrent.FutureTask;

public class MyViewModel extends AndroidViewModel {
    private SummaryCallable summaryCallable;

    public MyViewModel(@NonNull Application application) {
        super(application);
    }

    public SummaryLiveData getAnswer() throws Exception {
        FutureTask<Object> task = new FutureTask<>(summaryCallable);
        new Thread(task).start();
        return (SummaryLiveData) task.get();
    }

    public void setSummaryCallable(SummaryCallable summaryCallable) {
        this.summaryCallable = summaryCallable;
    }
}

SummaryCallable.java

// SummaryCallable.java
package com.weberhwang.testlivedata;

import androidx.lifecycle.LiveData;
import java.util.concurrent.Callable;

public class SummaryCallable implements Callable<Object> {
    private SummaryLiveData summaryLiveData;

    @Override
    public Object call() throws Exception {
        summaryLiveData.longJob();
        return summaryLiveData;
    }

    public void setSummaryLiveData(SummaryLiveData summaryLiveData) {
        this.summaryLiveData = summaryLiveData;
    }
}

SummaryLiveData.java

// SummaryLiveData.java
package com.weberhwang.testlivedata;

import androidx.lifecycle.LiveData;

public class SummaryLiveData extends LiveData {
    private int a = 1;
    private int b = 0;
    private int answer = 0;

    public void longJob() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        answer = a + b;
    }

    public void setB(int b) {  
        this.b = b;
    }

    public int getAnswer() {
        return answer;
    }
}

activity_main.xml

// activity_main.xml

package com.weberhwang.testlivedata;

import androidx.lifecycle.LiveData;

public class SummaryLiveData extends LiveData {
    private int a = 1;
    private int b = 0;
    private int answer = 0;

    public void longJob() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        answer = a + b;
    }

    public void setB(int b) {
        this.b = b;
    }

    public int getAnswer() {
        return answer;
    }
}

I fixed my program as following. Then it's work.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/result" />


</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

package com.weberhwang.testmutablelivedata;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import com.weberhwang.testmutablelivedata.databinding.ActivityMainBinding;

import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;
    private MyViewModel myViewModel;
    private TextView result;
    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        result = binding.result; 
        button = binding.button;

        result.setText("No answer");

        Summary summary = new Summary();
        summary.setB(2);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                summary.setB(3);
                try {
                    myViewModel.getAnswer(summary);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);

        try {
            myViewModel.getAnswer(summary).observe(this, new Observer<Summary>() {
                @Override
                public void onChanged(Summary s) {
                    result.setText(String.valueOf(s.getAnswer()));
                }
            });
        } catch (Exception e) {
            Log.d("MyLog", e.getMessage());
        }
    }
}

MyViewModel.java

package com.weberhwang.testmutablelivedata;

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;

import java.util.concurrent.FutureTask;

public class MyViewModel extends AndroidViewModel {
    private MutableLiveData<Summary> summaryMutableLiveData = new MutableLiveData<>();

    public MyViewModel(@NonNull Application application) {
        super(application);
    }

    public MutableLiveData<Summary> getAnswer(Summary summary) throws Exception {
        SummaryCallable summaryCallable = new SummaryCallable();
        summaryCallable.setSummary(summary);

        FutureTask<Object> task = new FutureTask<>(summaryCallable);
        new Thread(task).start();
        summaryMutableLiveData.setValue((Summary) task.get());
        return summaryMutableLiveData;
    }
}

Summary.java

package com.weberhwang.testmutablelivedata;

public class Summary {
    private int a = 1;
    private int b = 0;
    private int answer = 0;

    public void longJob() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        answer = a + b;
    }

    public void setB(int b) {
        this.b = b;
    }

    public int getAnswer() {
        return answer;
    }
}

SummaryCallable.java

package com.weberhwang.testmutablelivedata;

import java.util.concurrent.Callable;

public class SummaryCallable implements Callable<Object> {
    private Summary summary;

    @Override
    public Object call() throws Exception {
        summary.longJob();
        return summary;
    }

    public void setSummary(Summary summary) {
        this.summary = summary;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM