我有一个 Android 应用程序,我在其中使用 MVVM 和 Retrofit。
我想在这个应用程序中应用搜索,我有一个用于搜索的 api,并且 api 通过邮递员正确返回结果,但是当我尝试在 android 中构建它时,我感到很困惑,因为我得到了错误的结果。
这是我的代码
SearchRepo.java
public class SearchRepo {
private Application application;
private ApiService apiService;
public SearchRepo(Application application) {
this.application = application;
this.apiService = RetrofitClient.getClient(BASE_URL)
.create(ApiService.class);
}
public void SearchForKeyWord(String lang, String keyword, int perPage,
SearchRepositoryCallBack<ProductModel> callBack) {
apiService.search(lang,keyword,perPage)
.enqueue(new Callback<ProductModel>() {
@Override
public void onResponse(Call<ProductModel> call, Response<ProductModel> response) {
if (response.isSuccessful()) {
callBack.onSuccess(response.body());
} else {
callBack.onFailure("Error : "+response.code());
}
}
@Override
public void onFailure(Call<ProductModel> call, Throwable t) {
callBack.onFailure("Error : "+t.getMessage());
}
});
}
public interface SearchRepositoryCallBack<T> {
void onSuccess(T post);
void onFailure(String error);
}
}
SearchViewModel.java
public class SearchViewModel extends AndroidViewModel {
private SearchRepo search;
private MutableLiveData<ProductModel> searchResult = new MutableLiveData<>();
public SearchViewModel(@NonNull Application application) {
super(application);
this.search = new SearchRepo(application);
}
public void searchProducts(String lang,String keyword,int perPage) {
search.SearchForKeyWord(lang, keyword, perPage, new SearchRepo.SearchRepositoryCallBack<ProductModel>() {
@Override
public void onSuccess(ProductModel post) {
searchResult.postValue(post);
}
@Override
public void onFailure(String error) {
Log.e(APITAG,error);
}
});
}
public LiveData<ProductModel> getSearchResult() {
return searchResult;
}
}
searchFragment.java中的搜索方法
private void search(String lang, String keyword, int perPage) {
productViewModel.searchProduct(lang,keyword,perPage);
productViewModel.getResultList().observe(getViewLifecycleOwner(), new Observer<ProductModel>() {
@Override
public void onChanged(ProductModel productModel) {
List<Product> mlist = productModel.getData();
for (int i=0;i<mlist.size();i++) {
System.out.println(i);
System.out.println("My List "+mlist.size());
System.out.println("My List "+mlist.get(i).getName());
}
System.out.println("=====================================");
}
});
}
当我输入文本进行搜索时,我会得到正确的结果,但是如果我删除该单词并尝试编写另一个单词,我会得到旧的结果和正确的结果,结果的数量呈指数级增长。
示例
1
======
input -> m
expected -> "moon" , "mine"
actual output -> "moon" , "mine"
=====================
2
======
input -> a
expected -> "apple" , "alpha"
actual output -> "moon" , "mine" , "apple" , "alpha" , "apple" , "alpha"
====================
3
======
input -> l
expected -> "locus" , "lord"
actual output -> "apple" , "alpha" , "apple" , "alpha" , "locus" , "lord" , "locus" , "lord"
那么问题是什么以及如何解决它
每次在片段中调用
search(String lang, String keyword, int perPage)
时,您都会创建一个新的观察者,因此,第一次调用搜索函数时,您有一个观察者,第二次您有两个观察者,依此类推。它们都处于活动状态并工作,直到片段死亡,因此它们打印 searchResult
mutableLiveData 发出的新数据。
您必须只有一个观察者来观察您的
searchResult
可变实时数据,因此请将这段代码放入您的 onCreateView()
或任何其他在片段的整个生命周期中调用一次的函数中。
productViewModel.getResultList().observe(getViewLifecycleOwner(), new Observer<ProductModel>() {
@Override
public void onChanged(ProductModel productModel) {
List<Product> mlist = productModel.getData();
for (int i=0;i<mlist.size();i++) {
System.out.println(i);
System.out.println("My List "+mlist.size());
System.out.println("My List "+mlist.get(i).getName());
}
System.out.println("=====================================");
}
});
要搜索新字符串,只需使用以下代码:
productViewModel.searchProduct(lang,keyword,perPage);
不要创建新的观察者来获取新结果,新结果将可以在您在
onCreateView()
中创建的之前的观察者上访问。