如何在Java中使用androidx.lifecycle.ViewModelProvider

huangapple go评论82阅读模式
英文:

How to use the androidx.lifecycle.ViewModelProvider in Java

问题

我最近在学习关于架构组件的内容,正在按照旧教程使用旧方法进行操作:

mainActivityViewModel =
    new ViewModelProvider(this).get(MainActivityViewModel.class);

但在ViewModelProvider的文档中,唯一可用的构造函数是:

ViewModelProvider(ViewModelStoreOwner, Factory)ViewModelProvider(ViewModelStore, Factory)

所以我尝试了以下方法,但不确定在重写的方法中应该返回什么,它目前返回null,导致程序崩溃。

public class MainActivity extends AppCompatActivity {
    private NoteViewModel noteViewModel;

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

        noteViewModel = new ViewModelProvider(this, new ViewModelProvider.Factory() {
            @NonNull
            @Override
            public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
                return null;
            }
        }).get(NoteViewModel.class);

        noteViewModel.getAllNotes().observe(this, new Observer<List<NoteEntity>>() {
            @Override
            public void onChanged(List<NoteEntity> noteEntities) {
                Toast.makeText(MainActivity.this,"Changed",Toast.LENGTH_LONG).show();
            }
        });
    }
}

我的方法是否正确?我现在完全迷失了。我应该从重写的方法中返回什么?

英文:

I'm recently learning about the architectural components and was following the old tutorial where they used the old method:
<!-- language-all: java -->

mainActivityViewModel =
    new ViewModelProvider(this).get(MainActivityViewModel.class);

But in the documentation for the ViewModelProvider, the only constructors available are
ViewModelProvider(ViewModelStoreOwner, Factory) &
ViewModelProvider(ViewModelStore, Factory).

So I did something like this but I'm not sure what to do in the overridden method and it currently returns null that crashes the program.

public class MainActivity extends AppCompatActivity {
    private NoteViewModel noteViewModel;

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

        noteViewModel = new ViewModelProvider(this, new ViewModelProvider.Factory() {
            @NonNull
            @Override
            public &lt;T extends ViewModel&gt; T create(@NonNull Class&lt;T&gt; modelClass) {
                return null;
            }
        }).get(NoteViewModel.class);

        noteViewModel.getAllNotes().observe(this, new Observer&lt;List&lt;NoteEntity&gt;&gt;() {
            @Override
            public void onChanged(List&lt;NoteEntity&gt; noteEntities) {
                Toast.makeText(MainActivity.this,&quot;Changed&quot;,Toast.LENGTH_LONG).show();
            }
        });
    }
}

Is my approach correct? I'm absolutely lost right now. What am I supposed to return from the overridden method?

答案1

得分: 2

noteViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(NoteViewModel.class);

当我们在 ViewModel 的构造函数中传递参数时(除了 Application 参数),我们使用自定义的工厂。

在 Gradle 依赖中添加以下代码:

def lifecycle_version = "2.2.0"

// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
//
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
英文:

Use this

noteViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(getApplication())).get(NoteViewModel.class;

We use custom factory, when we pass param to the constructor of ViewModel (apart from Application param).

and gradle dependency in case,

def lifecycle_version = &quot;2.2.0&quot;

    // LiveData
    implementation &quot;androidx.lifecycle:lifecycle-livedata:$lifecycle_version&quot;
    //
    implementation &quot;androidx.lifecycle:lifecycle-common-java8:$lifecycle_version&quot;
    // ViewModel
    implementation &quot;androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version&quot;

答案2

得分: 1

首先,您需要在活动类中初始化 ViewModel,如下所示:

noteViewModel = ViewModelProvider(this).get(NoteViewModel.class);

NoteViewModel.java 中:

您需要为存储模型提供的更新数据定义 LiveData 变量,并将其更新传递到 ViewModel。

public class NoteViewModel extends AndroidViewModel {
    AppRepository appRepository;
    MediatorLiveData<List<NoteEntity>> mediatorData;
   
    public NoteViewModel (@NonNull Application application) {
        super(application);
        mediatorData = new MediatorLiveData<>();
        appRepository = new AppRepository(MyApplication.apiService, application.retrofit);
    }

    public MediatorLiveData<List<NoteEntity>> getMediatorLiveData() {
        return mediatorData;
    }

    public void getNoteEntry() {
        try {
            mediatorData.addSource(appRepository.getNoteEntry(), new Observer<List<NoteEntity>>() {
                @Override
                public void onChanged(@Nullable List<NoteEntity> data) {
                    mediatorData.postValue(data);
                }
            });
        } catch (Exception e) {

        }
    }
}

MainActivityonCreate() 方法中,注册观察者并从 ViewModel 调用 API:

noteViewModel.getMediatorLiveData().observe(this, new Observer<List<NoteEntity>>() {
    @Override
    public void onChanged(List<NoteEntity> noteEntities) {
        Toast.makeText(MainActivity.this, "Changed", Toast.LENGTH_LONG).show();
    }
});

noteViewModel.getNoteEntry();

AppRepository.java 文件如下:

class AppRepository() {
    ApiService apiService;
    Retrofit retrofit;

    public AppRepository(ApiService apiService, Retrofit retrofit) {
        this.apiService = apiService;
        this.retrofit = retrofit;
    }

    public MediatorLiveData<List<NoteEntity>> getNotes() {
        MediatorLiveData<List<NoteEntity>> data = new MediatorLiveData<List<NoteEntity>>();

        apiService.getNotes().enqueue(new Callback<List<NoteEntity>>() {
            @Override
            void onResponse(Call<List<NoteEntity>> call, Response<List<NoteEntity>> response) {
                if (response.isSuccessful()) {
                    if (response.body() != null) {
                        data.postValue(response.body()); //成功数据
                    } else {
                        data.postValue(null); //错误
                    }
                } else {
                    data.postValue(null); //错误
                }
            }

            @Override
            void onFailure(Call<List<NoteEntity>> call, Throwable t) {
                data.postValue(null); //错误
            }
        });

        return data;
    }
}
英文:

First you need to initialize viewmodel in activity class like :

noteViewModel = ViewModelProvider(this).get(NoteViewModel.class);

In NoteViewModel.java

You need to define livedata variable for storing updated data provided by model and update post to view model

NoteViewModel.java file look like :

public class NoteViewModel extends AndroidViewModel {
    AppRepository appRepository;
    MediatorLiveData&lt;List&lt;NoteEntity&gt;&gt; mediatorData;
   
    public NoteViewModel (@NonNull Application application) {
        super(application);
        mediatorData=new MediatorLiveData&lt;&gt;();
        appRepository=new AppRepository((MyApplication).apiService, application.retrofit);

    }

    public MediatorLiveData&lt;List&lt;NoteEntity&gt;&gt; getMediatorLiveData() {
        return mediatorVideoData;
    }

   

    public void getNoteEntry()
    {
        try {

            mediatorData.addSource(appRepository.getNoteEntry(), new Observer&lt;List&lt;NoteEntity&gt;&gt;() {
                @Override
                public void onChanged(@Nullable List&lt;NoteEntity&gt; data) {
                    mediatorData.postValue(data);
                }
            });
        }catch (Exception e)
        {

        }
    }

   
}

In onCreate() of Mainactivity register observer like and call the API from view model like

 noteViewModel.getMediatorLiveData().observe(this, new Observer&lt;List&lt;NoteEntity&gt;&gt;() {
            @Override
            public void onChanged(List&lt;NoteEntity&gt; noteEntities) {
                Toast.makeText(MainActivity.this,&quot;Changed&quot;,Toast.LENGTH_LONG).show();
            }
        });

  noteViewModel.getNoteEntry();

AppRepository.java file look like

class AppRepository() {
ApiService apiService;
Retrofit retrofit;
public AppRepository(ApiService apiService ,Retrofit retrofit){
 this.apiService = apiService;
 this.retrofit = retrofit;
}

    public MediatorLiveData&lt;List&lt;NoteEntity&gt;&gt;  getNotes() {

        MediatorLiveData&lt;List&lt;NoteEntity&gt;&gt; data = new MediatorLiveData&lt;List&lt;NoteEntity&gt;&gt;()
       
        apiService.getNotes()
            .enqueue(new Callback&lt;List&lt;NoteEntity&gt;&gt; {

                @Override 
                void onResponse(
                    Call&lt;List&lt;NoteEntity&gt;&gt; call,
                    Response&lt;List&lt;NoteEntity&gt;&gt; response
                ) {
                    if (response.isSuccessful()) {
                        if(response.body()!=null){
                        data.postValue(response.body()); //successfull data
                         }else{
                         data.postValue(null); //error
                         }
                        
                    } else {
                        data.postValue(null); //error
                    }
                }
                 @Override
                fun onFailure(
                    Call&lt;List&lt;NoteEntity&gt;&gt; call,
                    Throwable t
                ) {
                     data.postValue(null); //error 
                }
            })

        return data;
    }
}

答案3

得分: 1

Kotlin 代码。

在 build.gradle 中添加

    implementation "androidx.activity:activity-ktx:1.1.0"

然后

    val noteViewModel by viewModels<NoteViewModel>()
英文:

Kotlin Code.

In build.gradle add

implementation &quot;androidx.activity:activity-ktx:1.1.0&quot;

then

val noteViewModel by viewModels&lt;NoteViewModel&gt;()

答案4

得分: 0

找到了解决方法,经过4个小时的研究。

noteViewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication())).get(NoteViewModel.class);

另外,这些依赖项应该添加到 gradle 文件中。

def room_version = "2.2.5";
def lifecycle_version = "2.2.0";

implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"

implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

不确定错误是否是因为我漏掉了注解依赖,但现在一切都正常工作了。

英文:

Figured it out after 4 hours.

noteViewModel = new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(this.getApplication())).get(NoteViewModel.class);

Also these dependencies should be added to the gradle file.

    def room_version = &quot;2.2.5&quot;
    def lifecycle_version = &quot;2.2.0&quot;

    implementation &quot;androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version&quot;
// LiveData
    implementation &quot;androidx.lifecycle:lifecycle-livedata:$lifecycle_version&quot;
    annotationProcessor &quot;androidx.lifecycle:lifecycle-compiler:$lifecycle_version&quot;

    implementation &quot;androidx.room:room-runtime:$room_version&quot;
    annotationProcessor &quot;androidx.room:room-compiler:$room_version&quot;

Not sure if the error was caused because I missed the annotation dependency. But everything works now.

huangapple
  • 本文由 发表于 2020年8月24日 14:24:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/63555733.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定