[英]I am getting error while using retfofit with MVVM
I am trying to fetch data by using retrofit with MVVM Architecture.我正在尝试使用带有 MVVM 架构的 retrofit 来获取数据。 When I wanted to print the data on console, it works.
当我想在控制台上打印数据时,它可以工作。
But when I wanna use them on the RecyclerView
, I get this error:但是当我想在
RecyclerView
上使用它们时,我收到了这个错误:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.movieapp, PID: 4275 android.os.NetworkOnMainThreadException.
E/AndroidRuntime:致命异常:主进程:com.example.movieapp,PID:4275 android.os.NetworkOnMainThreadException。
Here is my codes:这是我的代码:
public class MovieRepository {
private static MovieService movieService;
private final MutableLiveData<List<Movie>> listOfPopularMovie ;
private static MovieRepository newsRepository;
public static MovieRepository getInstance(){
if(newsRepository == null){
newsRepository=new MovieRepository();
}
return newsRepository;
}
public MovieRepository(){
movieService= RetrofitService.getMovieService();
listOfPopularMovie=new MutableLiveData<>();
}
public MutableLiveData<List<Movie>> getListOfPopularMovie(String key,int page) {
Call<MovieResponse> popularMovies= movieService.getPopularMovie(key,page);
popularMovies.enqueue(new Callback<MovieResponse>() {
@Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
listOfPopularMovie.setValue(response.body().getResults());
}
@Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
listOfPopularMovie.postValue(null);
}
});
return listOfPopularMovie;
}
public class MainViewModel extends AndroidViewModel {
private MutableLiveData<List<Movie>> listOfPopularMovies = new MutableLiveData<>();
private MovieRepository movieRepository;
public MainViewModel(@NonNull Application application) {
super(application);
movieRepository = MovieRepository.getInstance();
}
public MutableLiveData<List<Movie>> getListOfPopularMovies(String key, int page) {
listOfPopularMovies=movieRepository.getListOfPopularMovie(key,page);
return listOfPopularMovies;
}
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private List<Movie> movies;
private Context mContext;
public MovieAdapter(Context context){
mContext=context;
}
@NonNull
@Override
public MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view= LayoutInflater.from(mContext).inflate(R.layout.item_view,parent,false);
return new MovieViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MovieViewHolder holder, int position) {
Movie movie=movies.get(position);
String currentTitle=movie.getTitle();
String imageUrl="https://image.tmdb.org/t/p/original";
imageUrl +=movie.getBackdrop_path();
try {
URL url=new URL(imageUrl);
Bitmap bmp=BitmapFactory.decodeStream(url.openConnection().getInputStream());
Drawable drawable=new BitmapDrawable(mContext.getResources(),bmp);
holder.image.setBackground(drawable);
holder.title.setText(currentTitle);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public int getItemCount() {
if(movies == null)
return 0;
return movies.size();
}
public void setMovie(List<Movie> taskEntries) {
movies = taskEntries;
notifyDataSetChanged();
}
class MovieViewHolder extends RecyclerView.ViewHolder {
LinearLayout image;
TextView title;
public MovieViewHolder(@NonNull View itemView) {
super(itemView);
image=itemView.findViewById(R.id.movie_image);
title=itemView.findViewById(R.id.movie_title);
}
}
public class MainActivity extends AppCompatActivity {
MovieAdapter movieAdapter;
RecyclerView recyclerView;
MainViewModel mainViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView= findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
movieAdapter= new MovieAdapter(this);
recyclerView.setAdapter(movieAdapter);
DividerItemDecoration decoration = new DividerItemDecoration(getApplicationContext(), VERTICAL);
recyclerView.addItemDecoration(decoration);
mainViewModel= new ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(MainViewModel.class);
mainViewModel.getListOfPopularMovies("9e2629973011b0744ce3b589dff1fb32",1).observe(this, new Observer<List<Movie>>() {
@Override
public void onChanged(List<Movie> movies) {
movieAdapter.setMovie(movies);
}
});
}
Your exception happened because you use network in UI thread.您的异常发生是因为您在 UI 线程中使用网络。
I found the problem in your MovieAdapter code.我在您的MovieAdapter代码中发现了问题。
@Override
public void onBindViewHolder(@NonNull MovieViewHolder holder, int position) {
......................
URL url = new URL(imageUrl);
Bitmap bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
Drawable drawable = new BitmapDrawable(mContext.getResources(),bmp);
holder.image.setBackground(drawable);
.............................
}
So you used url.openConnection() code in onBindViewHolder method of MovieAdapter class.因此,您在 MovieAdapter class 的 onBindViewHolder 方法中使用了 url.openConnection() 代码。 But onBindViewHolder is called in UI thread.
但是 onBindViewHolder 在 UI 线程中被调用。
So, Answer is you should not call this function in onBindViewHolder method.所以,答案是你不应该在 onBindViewHolder 方法中调用这个 function 。
My suggestion is you can use image load library such as Glide or Picasso.我的建议是您可以使用 Glide 或 Picasso 等图像加载库。
https://github.com/bumptech/glide https://github.com/bumptech/glide
https://github.com/square/picasso https://github.com/square/picasso
if you use Glide, your onBindViewHolder method like this.如果你使用 Glide,你的 onBindViewHolder 方法是这样的。
Glide.with(holder.image.getContext()).load(imageUrl).into(holder.image);
I hope this will be helpful.我希望这会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.