【问题标题】:I am getting error while using retfofit with MVVM将 retfofit 与 MVVM 一起使用时出现错误
【发布时间】:2021-06-25 14:48:22
【问题描述】:

我正在尝试使用带有 MVVM 架构的改造来获取数据。 当我想在控制台上打印数据时,它可以工作。

但是当我想在RecyclerView 上使用它们时,我得到了这个错误:

E/AndroidRuntime: 致命异常: main 进程:com.example.movi​​eapp,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);
        }
    });


}

【问题讨论】:

标签: android mvvm retrofit


【解决方案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/glide
https://github.com/square/picasso

如果你使用 Glide,你的 onBindViewHolder 方法是这样的。

Glide.with(holder.image.getContext()).load(imageUrl).into(holder.image);

我希望这会有所帮助。

【讨论】:

  • 如果对您有帮助,请接受我的回答。
猜你喜欢
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 2017-08-15
  • 2015-03-02
  • 2013-07-14
  • 2015-10-28
  • 2023-03-27
相关资源
最近更新 更多