简体   繁体   中英

Android ViewModel, update LiveData inside a timer

I would like to have count down timer in my mobile app, I have used ViewModel and LiveData to share the data between different activities and update the UI. I know the ViewModel & LiveData is working as I have a button which saves the data, but when I try the same from the timer I get the following error:

Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.

I think the "model = new ViewModelProvider(this).get(viewmodelclass.class);" is wrong, but I have tried to delay the timer before calling the ViewModel class so it has time to initialise all the variables. So not sure how to get the reference to the ViewModel class?

Any ideas how to fix this issue would be highly appreciated, as it seems a very simple but going around in circles trying to fix it.

MainActivity class

package com.example.viewmodellivedata_sandpit;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

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

public class MainActivity extends AppCompatActivity
{
    private Button buttonBack_activity;

    public viewmodelclass model;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       // Get a reference to the ViewModel
       model = new ViewModelProvider(this).get(viewmodelclass.class);
       LiveData<String> shoppingList = model.getshoppinglist();

       model.getshoppinglist().observe(this, new Observer<String>(){
       @Override
       public void onChanged(@Nullable String s)
       {
            Log.d("Debug", "String has been updated");
       }
    });
    TextView textView_1 = findViewById(R.id.textView1);
    buttonBack_activity = (Button) findViewById(R.id.button1);
    buttonBack_activity.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View view) {
            Log.d("Debug", "Button pressed");
            model.writedatatest("send text");
        }


    });

    TimerStateMachineClass mActivity= new TimerStateMachineClass();
    mActivity.starttimer();

    }

}

ViewModel class

package com.example.viewmodellivedata_sandpit;

import android.util.Log;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class viewmodelclass extends ViewModel {
public MutableLiveData<String> shoppingList;

public MutableLiveData<String> getshoppinglist() {
    if (shoppingList == null) {
        Log.w("Debug", "Inside the get shopping list");
        shoppingList = new MutableLiveData<>();
        writedatatest("test message");
    }
    return shoppingList;
  }

  public void writedatatest(String incomingdata)
  {
    Log.w("Debug", "Inside the get shopping list 1 -> "+shoppingList.getValue());
    shoppingList.postValue(incomingdata);
  }

}

Timer class

public class TimerStateMachineClass extends AppCompatActivity {

public Timer myTimer;
public viewmodelclass model;
int coutner;

public void starttimer()
{
    Log.w("Debug", "onCreate savedInstanceState");
    model = new ViewModelProvider(this).get(viewmodelclass.class);
    Log.w("Debug", "Function start timer");
    myTimer = new Timer();
    coutner = 0;
    myTimer.schedule(new TimerTask() {

        public void run() {
            TimerMethod();
        }

    }, 0, 1000);
}

  public void TimerMethod()
  {
    Log.w("Debug", "Timer execution");

   // LiveData<String> shoppingList = model.getshoppinglist();
    coutner++;
    model.writedatatest(Integer.toString(coutner));
  }
}

The answer was very simple just need to add onCreateView at the bottom of the code

 public class MainActivity extends AppCompatActivity
 {
     private Button buttonBack_activity;
     TextView textView_1;
     public static viewmodelclass model;
     @Override
     protected void onCreate(Bundle savedInstanceState)
     {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Get a reference to the ViewModel
        model = new ViewModelProvider(this).get(viewmodelclass.class);


    try{

        textView_1 = findViewById(R.id.textView1);
        buttonBack_activity = (Button) findViewById(R.id.button1);
        buttonBack_activity.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view) {
                Log.d("Debug", "Button pressed");
                model.writedatatest("send text");
            }


        });

        TimerStateMachineClass mActivity= new TimerStateMachineClass();
        mActivity.starttimer();
        LiveData<String> shoppingList = model.getshoppinglist();
        model.getshoppinglist().observe(this, new Observer<String>(){
            @Override
            public void onChanged(@Nullable String s)
            {
                textView_1.setText(s);
                Log.d("Debug", "String has been updated ->"+s);
            }
        });


    }catch (Exception e)
    {
        e.printStackTrace();
    }

    }

   @Nullable
   @Override
   public View onCreateView(@NonNull String name, @NonNull Context context, 
   @NonNull AttributeSet attrs) {

        return super.onCreateView(name, context, attrs);
  }
  }

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