TabLayout 中的 RecyclerView 适配器冲突

RecyclerView Adapter Conflict in a TabLayout

我的 Activity 中有一个包含 4 个选项卡的 TabLayout,我为每个选项卡制作了一个片段。

下面是我的 Activity 代码:

public class MyActivity extends AppCompatActivity {

private static final String TAG = "RecyclerView";
private Toolbar toolbar;
private static ViewPager viewPager;
private static TabLayout tabLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /* Allow activity to show indeterminate progressbar */
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

    setContentView(R.layout.student_regulations_list);
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    viewPager = (ViewPager) findViewById(R.id.viewPager);
    setupViewPager(viewPager);

    tabLayout = (TabLayout) findViewById(R.id.tabLayout);
    tabLayout.setupWithViewPager(viewPager);
    tabLayout.setOnTabSelectedListener(onTabSelectedListener(viewPager));
}

private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    adapter.addFragment(new Fragment1(), getString(R.string.titleA));
    adapter.addFragment(new Fragment2(), getString(R.string.titleB));
    adapter.addFragment(new Fragment3(), getString(R.string.titleC));
    adapter.addFragment(new Fragment4(), getString(R.string.titleD));
    viewPager.setAdapter(adapter);
    viewPager.setOffscreenPageLimit(3);
    viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}

private TabLayout.OnTabSelectedListener onTabSelectedListener(final ViewPager viewPager) {
    return new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            viewPager.setCurrentItem(tab.getPosition());//setting current selected item over viewpager
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
        }
    };
}

//View Pager fragments setting adapter class
class ViewPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();//fragment arraylist
    private final List<String> mFragmentTitleList = new ArrayList<>();//title arraylist

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    //adding fragments and title method
    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

我在每个片段中都有一个 RecyclerView,我使用 AsyncTask 从 Web 服务获取数据以显示在 RecyclerView 中。 RecyclerView 中的每个项目都有一个 ID,我想当我在选项卡之间切换并单击 RecyclerView 中的一个项目时,Toast 会显示它的 ID。

下面是片段代码:

public class Fragment1 extends Fragment implements ClickListener {

private static final String TAG = "RecyclerView";
private List<FeedItem> feedItemList;
private RecyclerView mRecyclerView;
private FeedsRecyclerAdapter mAdapter;
final String url = "a valid url";
private View rootView;
private ProgressBar progressBar;

public StuRegGeneralListFragment() {
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.fragment_student_regulations_list, container, false);
    return rootView;
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    progressBar = (ProgressBar) rootView.findViewById(R.id.progress_bar);

    /* Initialize recyclerview */
    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
    mRecyclerView.setHasFixedSize(true);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

    /*Downloading data from below url*/
    new AsyncHttpTask().execute(url);
}

@Override
public void itemClicked(View view, int position) {
    FeedItem item = feedItemList.get(position);

    Intent intent = new Intent(getActivity(), JsonRequestFeedActivity.class);
    intent.putExtra("url", Const.URL_JSON_OBJECT_REGS + item.getID());
    intent.putExtra("pid", item.getID());
    //startActivity(intent);
    Toast.makeText(getActivity(), "Item ID: " + item.getID(), Toast.LENGTH_SHORT).show();
}

public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {

    @Override
    protected void onPreExecute() {
        progressBar.setVisibility(View.VISIBLE);
        feedItemList = new ArrayList<FeedItem>();
    }

    @Override
    protected Integer doInBackground(String... params) {
        InputStream inputStream = null;
        Integer result = 0;
        HttpURLConnection urlConnection = null;

        try {
            /* forming th java.net.URL object */
            URL url = new URL(params[0]);

            urlConnection = (HttpURLConnection) url.openConnection();

            /* for Get request */
            urlConnection.setRequestMethod("GET");

            int statusCode = urlConnection.getResponseCode();

            /* 200 represents HTTP OK */
            if (statusCode == 200) {

                BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = r.readLine()) != null) {
                    response.append(line);
                }

                parseResult(response.toString());
                result = 1; // Successful
            } else {
                result = 0; //"Failed to fetch data!";
            }

        } catch (Exception e) {
            Log.d(TAG, e.getLocalizedMessage());
        }

        return result; //"Failed to fetch data!";
    }

    @Override
    protected void onPostExecute(Integer result) {
        progressBar.setVisibility(View.GONE);

        /* Download complete. Lets update UI */
        if (result == 1) {
            updateRecyclerView();
        } else {
            Log.e(TAG, "Failed to fetch data!");
        }
    }
}

private void parseResult(String result) {
    try {
        JSONObject response = new JSONObject(result);
        JSONArray posts = response.optJSONArray("posts");

        /*Initialize array if null*/
        if (null == feedItemList) {
            feedItemList = new ArrayList<FeedItem>();
        }

        for (int i = 0; i < posts.length(); i++) {
            JSONObject post = posts.optJSONObject(i);

            FeedItem item = new FeedItem();
            item.setID(post.optString("id"));
            item.setDate(post.optString("date"));
            item.setTitle(post.optString("title"));
            item.setThumbnail(post.optString("thumbnail"));
            feedItemList.add(item);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

public void updateRecyclerView() {
    mAdapter = new FeedsRecyclerAdapter(getActivity(), feedItemList);
    mRecyclerView.setAdapter(mAdapter);

    mAdapter.setClickListener(this);
}

}

假设每个片段在 RecyclerView 中有 5 个项目(在片段 1 中从 ID 1 到 5,在片段 2 中从 ID 6 到 10,...)我希望当我进入 Activity 并点击一个fragment1 中的项目(例如第一个项目),ID=1 显示在 Toast 中,但显示 ID=16!

其实是因为viewPager.setOffscreenPageLimit(3);在我的 Activity 中,创建了 fragment1 和 fagment2 以及 fragment3 和 fragment4,最后 mAdapter 包含项目 ID 16-20,尽管我在 fragment1 中。 我希望通过 viewPager.setOffscreenPageLimit(int) 创建指定的片段后;每个片段都有自己的适配器,但这并没有发生。

感谢任何帮助。

我发现了我的错误!

我的Activity和Fragments代码是正确的,我的错误在RecyclerView的ClickListener。它的实现不适合我的情况。

我在其中使用了静态 clickListener,这就是重点!