如何使用 Retrofit 调用 Json
How to call Json using Retrofit
我有 JSON 如下:
{
"Search": [
{
"Title": "Iron Man",
"Year": "2008"
},
{
"Title": "Iron Man2",
"Year": "20010"
},
{
"Title": "Iron Man3",
"Year": "2013"
}
]
}
然后我创建了 APIservice 如下:
public interface MyApi {
@GET("/movies")
Call<ArrayList<MovieSearch>> getartistdata();
}
我的数据class如下
public class MovieSearch {
@SerializedName("Search")
public List<Search> Search =null;
}
public class Search {
@SerializedName("Title")
public String Title="";
@SerializedName("Year")
public String Year="";
@SerializedName("Poster")
public String Poster="";
public Search() {
}
public Search(String Title, String Year, String Poster) {
this.Title = Title;
this.Year = Year;
}
}
现在我正在尝试实现视图模型 class,如下所示
public class MyListViewModel extends ViewModel {
public String Title = "";
public String Year= "";
public String Poster = "";
public MutableLiveData<ArrayList<MyListViewModel>> mutableLiveData = new MutableLiveData<>();
private ArrayList<MyListViewModel> arrayList;
private ArrayList<MovieSearch> myList;
public String getImageurl() {
return Poster;
}
@BindingAdapter({"imageUrl"})
public static void loadimage(ImageView imageView, String imageUrl) {
Glide.with(imageView.getContext()).load(imageUrl).apply(RequestOptions.circleCropTransform()).into(imageView);
//Picasso.with(imageView.getContext()).load(imageUrl).into(imageView);
}
public MyListViewModel() {
}
public MyListViewModel(MovieSearch myList) {
this.Title = myList.Title;
this.Poster = myList.Poster;
this.Year= myList.Year;
}
public MutableLiveData<ArrayList<MyListViewModel>> getMutableLiveData() {
arrayList = new ArrayList<>();
MyApi api = MyClient.getInstance().getMyApi();
Call<ArrayList<MovieSearch>> call = api.getartistdata();
call.enqueue(new Callback<ArrayList<MovieSearch>>() {
@Override
public void onResponse(Call<ArrayList<MovieSearch>> call, Response<ArrayList<MovieSearch>> response) {
myList = new ArrayList<>();
myList = response.body();
for (int i = 0; i < myList.size(); i++) {
MovieSearch myk = myList.get(i);
MyListViewModel myListViewModel = new MyListViewModel(myk);
arrayList.add(myListViewModel);
mutableLiveData.setValue(arrayList);
}
}
@Override
public void onFailure(Call<ArrayList<MovieSearch>> call, Throwable t) {
}
});
return mutableLiveData;
}
}
但我收到以下 "Cannot resolve symbol" 错误:
public MyListViewModel(MovieSearch myList) {
this.Title = myList.Title;
this.Poster = myList.Poster;
this.Year= myList.Year;
}
我正在尝试从 JSON 获取数据并将其绑定到视图持有者。但我无法弄清楚如何称呼它。有人请帮我解决它。
在这里我注意到您保留了一个 ViewModel 数组。最主要的是 ViewModel 不应该那样使用。
我认为最好阅读一些 ViewModel 的文档和示例实现以更好地理解。
关于您的实施,一切看起来都很好,但有一件事正在将您的 MovieSearch
列表转换为 MyListViewModel
列表。
在 ViewModel 中
public class MyListViewModel extends ViewModel {
private MutableLiveData<MovieSearch> mutableLiveData = new MutableLiveData<>();
@BindingAdapter({"imageUrl"})
public static void loadimage(ImageView imageView, String imageUrl) {
Glide.with(imageView.getContext()).load(imageUrl).apply(RequestOptions.circleCropTransform()).into(imageView);
//Picasso.with(imageView.getContext()).load(imageUrl).into(imageView);
}
public LiveData<MovieSearch> getMutableLiveData() {
loadData();
return mutableLiveData;
}
private void loadData(){
MyApi api = MyClient.getInstance().getMyApi();
Call<MovieSearch> call = api.getartistdata();
call.enqueue(new Callback<MovieSearch>() {
@Override
public void onResponse(Call<MovieSearch> call, Response<MovieSearch> response) {
MovieSearch movieSearch = response.body();
mutableLiveData.setValue(myList);
}
@Override
public void onFailure(Call<ArrayList<MovieSearch>> call, Throwable t) {
}
});
}
}
在activity或fragment中,可以通过getMutableLiveData()
访问liveData并将List<MovieSearch>
设置为adapter。
另外一件事,根据您的回复 JSON,您的 API 应该喜欢下面的内容
public interface MyApi {
@GET("/movies")
Call<MovieSearch> getartistdata();
}
MovieSearch
不在列表中
适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<Search> arrayList = new ArrayList<>;
private LayoutInflater layoutInflater;
public void submitList(ArrayList<Search> searchList){
this.arrayList = searchList;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (layoutInflater==null){
layoutInflater=LayoutInflater.from(parent.getContext());
}
MyListBinding myListBinding= DataBindingUtil.inflate(layoutInflater, R.layout.mylist,parent,false);
return new ViewHolder(myListBinding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Search search =arrayList.get(position);
holder.bind(search);
}
@Override
public int getItemCount() {
return arrayList.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
private MyListBinding myListBinding;
public ViewHolder(@NonNull MyListBinding myListBinding) {
super(myListBinding.getRoot());
this.myListBinding=myListBinding;
}
public void bind(Search myli){
this.myListBinding.setMylistmodel(myli);
myListBinding.executePendingBindings();
}
public MyListBinding getMyListBinding(){
return myListBinding;
}
}
}
Activity
adapter = MyAdapter();
recyclerview=(RecyclerView)findViewById(R.id.recyclerView);
recyclerview.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerview.setAdapter(adapter);
myListViewModel = ViewModelProviders.of(this).get(MyListViewModel.class);
myListViewModel.getSearchResults().observe(this, new Observer<MovieSearch>() {
@Override
public void onChanged(@Nullable MovieSearch movieSearch) {
// handle changes here, to use the data write code below
adapter.submitList(movieSearch.Search);
}
});
还有一件小事,请不要以大写字母开头变量名。最好从一开始就遵循命名约定。
您已经非常接近了,您只需对服务 class 和视图模型进行少量更改即可使其正常工作。进行以下更改
MyApi 接口: -> 因为你的 json 不是 arraylist 而是 MovieSearch 的一个对象所以在搜索的 arraylist 里面做相应的改变。
public interface MyApi {
@GET("/movies")
Call<MovieSearch> getartistdata();
}
MyListViewModel class:
public class MyListViewModel extends ViewModel {
public MutableLiveData<ArrayList<Search>> mutableLiveData = new MutableLiveData<>();
@BindingAdapter({"imageUrl"})
public static void loadimage(ImageView imageView, String imageUrl) {
Glide.with(imageView.getContext()).load(imageUrl).apply(RequestOptions.circleCropTransform()).into(imageView);
//Picasso.with(imageView.getContext()).load(imageUrl).into(imageView);
}
public MyListViewModel() {
//do something else, your view model is not POJO it's the handler not storage.
}
public MutableLiveData<ArrayList<Search>> getSearchResults() {
MutableLiveData<ArrayList<Search>> localData = new MutableLiveData<>();
MyApi api = MyClient.getInstance().getMyApi();
Call<MovieSearch> call = api.getartistdata();
call.enqueue(new Callback<MovieSearch>() {
@Override
public void onResponse(Call<MovieSearch> call, Response<MovieSearch> response) {
List<Search> myList = response.body().Search;
mutableLiveData.setValue(myList);
localData.setValue(myList);
}
@Override
public void onFailure(Call<ArrayList<MovieSearch>> call, Throwable t) {
//handle the error
}
});
return localData;
}
}
通过创建一个视图模型对象和一些函数来调用上面的视图模型。这部分通常放在一些 UI class activity 或片段中:
//listening for change in live data
// this would be in ui layer
myListViewModelObject.getSearchResults().observe(this, new Observer<ArrayList<Search>>() {
@Override
public void onChanged(@Nullable ArrayList<Search> obj) {
// handle changes here, to use the data write code below
}
});
建议:不要使用您的 viewmodel 来存储数据,因为它不是专门用来存储数据的。它用于处理数据和操作,而不是数据的管理员。在视图模型中管理数据和业务逻辑会导致很多问题。如果可能,请始终将事物分解成更小的部分,例如,从其他一些 class 获取改造对象,或者不要将其放在调用方法本身中,这将导致代码重复并可能影响性能。
注意:我还没有测试代码,只是做了最好的修改,应该运行。如果我删除了任何内容,请添加缺少的部分。
我有 JSON 如下:
{
"Search": [
{
"Title": "Iron Man",
"Year": "2008"
},
{
"Title": "Iron Man2",
"Year": "20010"
},
{
"Title": "Iron Man3",
"Year": "2013"
}
]
}
然后我创建了 APIservice 如下:
public interface MyApi {
@GET("/movies")
Call<ArrayList<MovieSearch>> getartistdata();
}
我的数据class如下
public class MovieSearch {
@SerializedName("Search")
public List<Search> Search =null;
}
public class Search {
@SerializedName("Title")
public String Title="";
@SerializedName("Year")
public String Year="";
@SerializedName("Poster")
public String Poster="";
public Search() {
}
public Search(String Title, String Year, String Poster) {
this.Title = Title;
this.Year = Year;
}
}
现在我正在尝试实现视图模型 class,如下所示
public class MyListViewModel extends ViewModel {
public String Title = "";
public String Year= "";
public String Poster = "";
public MutableLiveData<ArrayList<MyListViewModel>> mutableLiveData = new MutableLiveData<>();
private ArrayList<MyListViewModel> arrayList;
private ArrayList<MovieSearch> myList;
public String getImageurl() {
return Poster;
}
@BindingAdapter({"imageUrl"})
public static void loadimage(ImageView imageView, String imageUrl) {
Glide.with(imageView.getContext()).load(imageUrl).apply(RequestOptions.circleCropTransform()).into(imageView);
//Picasso.with(imageView.getContext()).load(imageUrl).into(imageView);
}
public MyListViewModel() {
}
public MyListViewModel(MovieSearch myList) {
this.Title = myList.Title;
this.Poster = myList.Poster;
this.Year= myList.Year;
}
public MutableLiveData<ArrayList<MyListViewModel>> getMutableLiveData() {
arrayList = new ArrayList<>();
MyApi api = MyClient.getInstance().getMyApi();
Call<ArrayList<MovieSearch>> call = api.getartistdata();
call.enqueue(new Callback<ArrayList<MovieSearch>>() {
@Override
public void onResponse(Call<ArrayList<MovieSearch>> call, Response<ArrayList<MovieSearch>> response) {
myList = new ArrayList<>();
myList = response.body();
for (int i = 0; i < myList.size(); i++) {
MovieSearch myk = myList.get(i);
MyListViewModel myListViewModel = new MyListViewModel(myk);
arrayList.add(myListViewModel);
mutableLiveData.setValue(arrayList);
}
}
@Override
public void onFailure(Call<ArrayList<MovieSearch>> call, Throwable t) {
}
});
return mutableLiveData;
}
}
但我收到以下 "Cannot resolve symbol" 错误:
public MyListViewModel(MovieSearch myList) {
this.Title = myList.Title;
this.Poster = myList.Poster;
this.Year= myList.Year;
}
我正在尝试从 JSON 获取数据并将其绑定到视图持有者。但我无法弄清楚如何称呼它。有人请帮我解决它。
在这里我注意到您保留了一个 ViewModel 数组。最主要的是 ViewModel 不应该那样使用。
我认为最好阅读一些 ViewModel 的文档和示例实现以更好地理解。
关于您的实施,一切看起来都很好,但有一件事正在将您的 MovieSearch
列表转换为 MyListViewModel
列表。
在 ViewModel 中
public class MyListViewModel extends ViewModel {
private MutableLiveData<MovieSearch> mutableLiveData = new MutableLiveData<>();
@BindingAdapter({"imageUrl"})
public static void loadimage(ImageView imageView, String imageUrl) {
Glide.with(imageView.getContext()).load(imageUrl).apply(RequestOptions.circleCropTransform()).into(imageView);
//Picasso.with(imageView.getContext()).load(imageUrl).into(imageView);
}
public LiveData<MovieSearch> getMutableLiveData() {
loadData();
return mutableLiveData;
}
private void loadData(){
MyApi api = MyClient.getInstance().getMyApi();
Call<MovieSearch> call = api.getartistdata();
call.enqueue(new Callback<MovieSearch>() {
@Override
public void onResponse(Call<MovieSearch> call, Response<MovieSearch> response) {
MovieSearch movieSearch = response.body();
mutableLiveData.setValue(myList);
}
@Override
public void onFailure(Call<ArrayList<MovieSearch>> call, Throwable t) {
}
});
}
}
在activity或fragment中,可以通过getMutableLiveData()
访问liveData并将List<MovieSearch>
设置为adapter。
另外一件事,根据您的回复 JSON,您的 API 应该喜欢下面的内容
public interface MyApi {
@GET("/movies")
Call<MovieSearch> getartistdata();
}
MovieSearch
不在列表中
适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<Search> arrayList = new ArrayList<>;
private LayoutInflater layoutInflater;
public void submitList(ArrayList<Search> searchList){
this.arrayList = searchList;
notifyDataSetChanged();
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (layoutInflater==null){
layoutInflater=LayoutInflater.from(parent.getContext());
}
MyListBinding myListBinding= DataBindingUtil.inflate(layoutInflater, R.layout.mylist,parent,false);
return new ViewHolder(myListBinding);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Search search =arrayList.get(position);
holder.bind(search);
}
@Override
public int getItemCount() {
return arrayList.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
private MyListBinding myListBinding;
public ViewHolder(@NonNull MyListBinding myListBinding) {
super(myListBinding.getRoot());
this.myListBinding=myListBinding;
}
public void bind(Search myli){
this.myListBinding.setMylistmodel(myli);
myListBinding.executePendingBindings();
}
public MyListBinding getMyListBinding(){
return myListBinding;
}
}
}
Activity
adapter = MyAdapter();
recyclerview=(RecyclerView)findViewById(R.id.recyclerView);
recyclerview.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerview.setAdapter(adapter);
myListViewModel = ViewModelProviders.of(this).get(MyListViewModel.class);
myListViewModel.getSearchResults().observe(this, new Observer<MovieSearch>() {
@Override
public void onChanged(@Nullable MovieSearch movieSearch) {
// handle changes here, to use the data write code below
adapter.submitList(movieSearch.Search);
}
});
还有一件小事,请不要以大写字母开头变量名。最好从一开始就遵循命名约定。
您已经非常接近了,您只需对服务 class 和视图模型进行少量更改即可使其正常工作。进行以下更改
MyApi 接口: -> 因为你的 json 不是 arraylist 而是 MovieSearch 的一个对象所以在搜索的 arraylist 里面做相应的改变。
public interface MyApi {
@GET("/movies")
Call<MovieSearch> getartistdata();
}
MyListViewModel class:
public class MyListViewModel extends ViewModel {
public MutableLiveData<ArrayList<Search>> mutableLiveData = new MutableLiveData<>();
@BindingAdapter({"imageUrl"})
public static void loadimage(ImageView imageView, String imageUrl) {
Glide.with(imageView.getContext()).load(imageUrl).apply(RequestOptions.circleCropTransform()).into(imageView);
//Picasso.with(imageView.getContext()).load(imageUrl).into(imageView);
}
public MyListViewModel() {
//do something else, your view model is not POJO it's the handler not storage.
}
public MutableLiveData<ArrayList<Search>> getSearchResults() {
MutableLiveData<ArrayList<Search>> localData = new MutableLiveData<>();
MyApi api = MyClient.getInstance().getMyApi();
Call<MovieSearch> call = api.getartistdata();
call.enqueue(new Callback<MovieSearch>() {
@Override
public void onResponse(Call<MovieSearch> call, Response<MovieSearch> response) {
List<Search> myList = response.body().Search;
mutableLiveData.setValue(myList);
localData.setValue(myList);
}
@Override
public void onFailure(Call<ArrayList<MovieSearch>> call, Throwable t) {
//handle the error
}
});
return localData;
}
}
通过创建一个视图模型对象和一些函数来调用上面的视图模型。这部分通常放在一些 UI class activity 或片段中:
//listening for change in live data
// this would be in ui layer
myListViewModelObject.getSearchResults().observe(this, new Observer<ArrayList<Search>>() {
@Override
public void onChanged(@Nullable ArrayList<Search> obj) {
// handle changes here, to use the data write code below
}
});
建议:不要使用您的 viewmodel 来存储数据,因为它不是专门用来存储数据的。它用于处理数据和操作,而不是数据的管理员。在视图模型中管理数据和业务逻辑会导致很多问题。如果可能,请始终将事物分解成更小的部分,例如,从其他一些 class 获取改造对象,或者不要将其放在调用方法本身中,这将导致代码重复并可能影响性能。
注意:我还没有测试代码,只是做了最好的修改,应该运行。如果我删除了任何内容,请添加缺少的部分。