将 retfofit 与 MVVM 一起使用时出现错误
Posted
技术标签:
【中文标题】将 retfofit 与 MVVM 一起使用时出现错误【英文标题】:I am getting error while using retfofit with MVVM 【发布时间】:2021-06-25 14:48:22 【问题描述】:我正在尝试使用带有 MVVM 架构的改造来获取数据。 当我想在控制台上打印数据时,它可以工作。
但是当我想在RecyclerView
上使用它们时,我得到了这个错误:
E/androidRuntime: 致命异常: main 进程:com.example.movieapp,PID:4275 android.os.NetworkOnMainThreadException。
这是我的代码:
电影资料库
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);
);
【问题讨论】:
这能回答你的问题吗? How to fix 'android.os.NetworkOnMainThreadException'? 【参考方案1】:您的异常发生是因为您在 UI 线程中使用了网络。 我在您的 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);
.............................
所以你在 MovieAdapter 类的 onBindViewHolder 方法中使用了 url.openConnection() 代码。 但是 onBindViewHolder 是在 UI 线程中调用的。
所以,答案是你不应该在 onBindViewHolder 方法中调用这个函数。
我的建议是你可以使用 Glide 或 Picasso 等图片加载库。
https://github.com/bumptech/glidehttps://github.com/square/picasso
如果你使用 Glide,你的 onBindViewHolder 方法是这样的。
Glide.with(holder.image.getContext()).load(imageUrl).into(holder.image);
我希望这会有所帮助。
【讨论】:
如果对您有帮助,请接受我的回答。以上是关于将 retfofit 与 MVVM 一起使用时出现错误的主要内容,如果未能解决你的问题,请参考以下文章
将 Typescript 与 React-Redux 一起使用时出现类型错误
将 Firebase 与 RecyclearView 一起使用时出现错误
将 QuerydslPredicateExecutor 与 JpaRepository 一起使用时出现 IllegalAccessException