Простой пример фрагмента приращения переменной с использованием ViewModel и LiveData - переменная всегда равна нулю - PullRequest
0 голосов
/ 15 сентября 2018

Примечание: я новичок в кодировании и пытаюсь следовать простому примеру в соответствии с заголовком.

Кажется, все идет хорошо, кроме менявозникли проблемы при увеличении переменной в методе onClick() в Tab1Fragment.Значение переменной value всегда равно null.

Я думаю, это как-то связано со смешением Interger с LiveData<Integer>, но я не уверен, что с этим делать.Я перепробовал все виды методов, чтобы преобразовать один в другой и обратно получить / сохранить результаты.В руководстве, которому я следовал ( ссылка ), используется метод .setValue(), но android studio не разрешит мне использовать этот метод.

Мне бы очень хотелось внести свой вклад в исправление этого, или даже простоссылка на супер простое руководство по фрагментам вкладок, которое я мог бы скопировать вставить в проект и изучить, как все это работает.Я уверен, что есть более простой способ выполнить эту задачу, но я хочу понять, как использовать эту концепцию для будущих проектов.

Спасибо.

Tab1Fragment.java

package com.example.android.tabsharer;

import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

public class Tab1Fragment extends Fragment {
    private static final String TAG = "Tab1Fragment";

    public SharedViewModel model;

    public LiveData<Integer> score;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.tab1_fragment, container, false);

//      Get the viewmodel
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

//      Create observer to update the fragment
        TextView score1 = getActivity().findViewById(R.id.score1);

        final Observer<Integer> scoreObserver = new Observer<Integer>() {
            @Override
            public void onChanged(@Nullable Integer newScore) {
                //Update the textview that holds the score
                score1.setText(newScore);
            }
        };

//      Observe the live data
        model.getScore().observe(getActivity(), scoreObserver);

// Create the button in java, set listener on it, increment score, and store to viewmodel
        final Button button = view.findViewById(R.id.editScore1);

        button.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
//              Basically every version of this comes up as null
                Integer value = model.getScore().getValue();
                if (value != null){
                    model.storeScore(++value);
                }
                else {
                    model.storeScore(0);
                }

            }
        });

        return view;
    }
}

SharedModelView.java

package com.example.android.tabsharer;

import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.support.annotation.NonNull;
import android.util.Log;

public class SharedViewModel extends AndroidViewModel {

    public static final String TAG = "SharedViewModel";

    private MutableLiveData<Integer> mScore = new MutableLiveData<>();

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

    public Integer storeScore(Integer score) {
        Log.d(TAG, "Score is being stored is " + mScore);
        mScore.setValue(score);
        return score;
    }

    public LiveData<Integer> getScore() {
        Log.d(TAG, "Score is being retrieved");
        if (mScore == null){
            mScore = new MutableLiveData<>();
            mScore.setValue(0);
        }
        return mScore;
    }
}

MainActivity.java

package com.example.android.tabsharer;

import android.arch.lifecycle.ViewModel;
import android.arch.lifecycle.ViewModelProvider;
import android.arch.lifecycle.ViewModelProviders;
import android.support.design.widget.TabLayout;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;


public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    public SharedViewModel model;

    private SectionsPageAdapter mSectionsPageAdapter;

    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate: Starting.");

        model = ViewModelProviders.of(this).get(SharedViewModel.class);

        mSectionsPageAdapter = new SectionsPageAdapter(getSupportFragmentManager());

        mViewPager = (ViewPager) findViewById(R.id.container);
        setupViewPager(mViewPager);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);

    }

    private void setupViewPager(ViewPager viewPager) {
        SectionsPageAdapter adapter = new SectionsPageAdapter(getSupportFragmentManager());
        adapter.addFragment(new Tab1Fragment(), "TAB1");
        adapter.addFragment(new Tab2Fragment(), "TAB2");
        viewPager.setAdapter(adapter);
    }


}

1 Ответ

0 голосов
/ 15 сентября 2018

Ваши проблемы с двумя вещами здесь,


Выпуск 1: (Необязательно)

// Observe the live data
model.getScore().observe(getActivity(), scoreObserver);

Вы используете наблюдателя внутри Fragment, поэтому вы должны использовать его LifeCycle для наблюдения следующим образом:

// Observe the live data
model.getScore().observe(this, scoreObserver);

Проблема 2: в том, что вы используете Integer в качестве оболочки внутри LiveData, которая не инициализируется во время этого метода:

public LiveData<Integer> getScore() {
    Log.d(TAG, "Score is being retrieved");
    if (mScore == null){//This code won't execute because you've initialized it globally.
        mScore = new MutableLiveData<>();
        mScore.setValue(0);
    }
    return mScore;
}

Итак, попробуйте изменить Interger на int, и он будет инициализирован с значением по умолчанию 0 .

Потому что Integer будет null здесь:

// Basically every version of this comes up as null
Integer value = model.getScore().getValue();

Решение: Измените private MutableLiveData<Integer> mScore = new MutableLiveData<>(); на private MutableLiveData<int> mScore = new MutableLiveData<>(); (оно будет показывать ошибку везде, где вы используете LiveData, поэтому измените его на int там)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...