Retrofit RecyclerView在选项卡布局中无法工作

3
我正在尝试在一个Fragment中使用Retrofit库解析数据并展示在RecyclerView中。但每当我运行项目时,列表都不显示,并且监视器显示“E/RecyclerView: No adapter attached; skipping layout”。以下是我的代码: MainActivity:
package com.example.ahmed.newsapp

import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.design.widget.TabLayout;

public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private  static final int ACTIVITY_NUM = 0;
// TODO - insert your themoviedb.org API KEY here
private final static String API_KEY = "<API KEY CENSORED>";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // Find the view pager that will allow the user to swipe between fragments
    ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);

    // Create an adapter that knows which fragment should be shown          

    FragmentAdapter adapter = new FragmentAdapter(getSupportFragmentManager
    ());
    // Set the adapter onto the view pager
    viewPager.setAdapter(adapter);
    TabLayout ob=(TabLayout) findViewById(R.id.sliding_tabs);
    ob.setupWithViewPager(viewPager);
}
}

FragmentAdapter:

package com.example.ahmed.newsapp;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

/**
 * Created by ahmed on 3/22/2017.
 */

public class FragmentAdapter extends FragmentPagerAdapter {
private String tabs[]=new String[]{"Home","Family Members","Colors"};
public FragmentAdapter(FragmentManager fm){
    super(fm);
}

@Override
public Fragment getItem(int position) {
   switch(position){
       case 0:
           return new HomeActivity();
       case 1:
           return new HomeActivity();
      /* case 2:
           return new ColorFragment();*/
   }
    return null;
}
@Override
public CharSequence getPageTitle(int position) {
return tabs[position];


}


@Override
public int getCount() {
    return 2;
}
}

新闻适配器:

package com.example.ahmed.newsapp;



 /**
    * Created by ahmed on 27-08-17.
    */
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.List;

public class NewsAdapter extends  RecyclerView.Adapter<NewsAdapter.NewsViewHolder> {

private List<News> news;
private int rowLayout;
private Context context;


public static class NewsViewHolder extends RecyclerView.ViewHolder {
    LinearLayout moviesLayout;
    TextView movieTitle;
    TextView data;
    TextView movieDescription;
    TextView rating;


    public NewsViewHolder(View v) {
        super(v);
        moviesLayout = (LinearLayout) v.findViewById(R.id.movies_layout);
        movieTitle = (TextView) v.findViewById(R.id.title);
        data = (TextView) v.findViewById(R.id.subtitle);
        movieDescription = (TextView) v.findViewById(R.id.description);
        rating = (TextView) v.findViewById(R.id.rating);
    }
}

public NewsAdapter(List<News> news, Context context) {
    this.news = news;
   // this.rowLayout = rowLayout;
    this.context = context;
}

@Override
public NewsViewHolder onCreateViewHolder(ViewGroup parent,
                                         int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.list_item_news, parent, false);
    return new NewsViewHolder(view);
}


@Override
public void onBindViewHolder(NewsViewHolder holder, final int position) {
    holder.movieTitle.setText(news.get(position).getTitle());
    holder.data.setText(news.get(position).getReleaseDate());
    holder.movieDescription.setText(news.get(position).getOverview());
    holder.rating.setText(news.get(position).getVoteAverage().toString());
}

@Override
public int getItemCount() {
    return news.size();
}
}

主页活动:

package com.example.ahmed.newsapp;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import static android.content.ContentValues.TAG;

public class HomeActivity extends Fragment {

RecyclerView recyclerView;
private final static String API_KEY = "<API KEY CENSORED>";
NewsAdapter adapter;
List<News> news,dummy;
View rootview;
public HomeActivity() {
    // Required empty public constructor
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    rootview = inflater.inflate(R.layout.activity_home, container, false);

    if (API_KEY.isEmpty()) {
        Toast.makeText(getContext(), "Please obtain your API KEY first from themoviedb.org", Toast.LENGTH_LONG).show();
        return rootview;
    }

    ApiInterface apiService =
            ApiClient.getClient().create(ApiInterface.class);

    recyclerView = (RecyclerView) rootview.findViewById(R.id.home_page_recycler_view);
    adapter= new NewsAdapter(dummy,getContext());
    Call<NewsResponse> call = apiService.getTopRatedMovies(API_KEY);
    call.enqueue(new Callback<NewsResponse>() {

        @Override
        public void onResponse(Call<NewsResponse> call, Response<NewsResponse> response) {
            news = response.body().getResults();
            adapter.notifyDataSetChanged();
            adapter=new NewsAdapter(news,getContext());

            recyclerView.setAdapter(adapter);
          //  adapter.setData(news);
            Log.d(TAG, "Number of movies received: " + news.size());
        }

        @Override
        public void onFailure(Call<NewsResponse> call, Throwable t) {
            // Log error here since request failed
            Log.e(TAG, t.toString());
        }
    });
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
    return rootview;
}
}

“Number of movies received:” 被打印了吗? - Programming Pirate
1
在片段的setUserVisibleHint()方法上调用API,并使用if(isVisibleToUser)变量。 - Piyush
请问 @Piyush,你能提供一个关于你建议的代码片段吗? - Ahmed Husnein Choudhury
我建议不要将你的片段命名为活动,因为它是一个片段而不是一个活动。HomeActivity需要重命名! - RazorHead
2个回答

0

我认为问题出在你的FragmentAdapter类中

只需从你的FragmentAdapter中删除return null;语句,就像下面的代码一样

    @Override
public Fragment getItem(int position) {
     Fragment fragment=null;
   switch(position){
       case 0:
            fragment= new HomeActivity();
       case 1:
           fragment= new HomeActivity();
      /* case 2:
           return new ColorFragment();*/
   }
    return fragment;
}

更改这个

 recyclerView.setHasFixedSize(true);
 recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
recyclerView = (RecyclerView) rootview.findViewById(R.id.home_page_recycler_view);
adapter= new NewsAdapter(dummy,getContext());

@AhmedHusneinChoudhury 任何异常 - AskNilesh
没有错误或异常。列表没有显示,但数据已经正确地存储在数组列表中。 - Ahmed Husnein Choudhury
@AhmedHusneinChoudhury 请检查更新的答案,并在将适配器设置到您的“recyclerView”之前尝试使用“LinearLayoutManager”。 - AskNilesh

0

当您收到响应时,无需重新创建适配器。

可能看起来像:

recyclerView = (RecyclerView) rootview.findViewById(R.id.home_page_recycler_view); 
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
adapter = new NewsAdapter(null, getActivity());
recyclerView.setAdapter(adapter);
Call<NewsResponse> call = apiService.getTopRatedMovies(API_KEY);
call.enqueue(new Callback<NewsResponse>() {

    @Override
    public void onResponse(Call<NewsResponse> call, Response<NewsResponse> response) {
        news = response.body().getResults();
        adapter.setData(news);
        Log.d(TAG, "Number of movies received: " + news.size());
    }

  ...

而在 NewsAdapter 中:

...

public void setData(Collection<News> newData) {
    news.clear();
    news.addAll(newData);
    notifyDataSetChanged();
}

@Override
public int getItemCount() {
    return news == null ? 0 : news.size();
}

...

@AhmedHusneinChoudhury忘记在设置适配器之前添加LayoutManager。尝试在onCreateViewHolder中打印一些日志。它被调用了多少次?你确定你在预期的选项卡中吗?答案已更新。 - Ivan Anisimov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接