Android : FragmentList 项目重复自己

Android : FragmentList items repeating themselves

我在我的 MainActivity 中创建了一个包含 5 个选项卡的 ViewPager。在第一个选项卡中,我放置了一个 ListView 以显示一些项目。问题是每当我滑动到另一个选项卡然后 return 滑动到第一个时,列表中的项目就会重复(即列表包含 A-B-C,然后是 A-B-C-A-B-C)。奇怪的是,只有当我滑动比第二个选项卡更远时才会发生这种情况。这是我的代码:

主要活动:

public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
    private ViewPager viewPager;
    private TabsPagerAdapter mAdapter;
    private ActionBar actionBar;

    //private String[] tabs = { "Mixed", "Videos", "Audio", "Text", "Picture" };
    final int[] ICONS = new int[] {
            R.drawable.mixed,
            R.drawable.video,
            R.drawable.audio,
            R.drawable.note,
            R.drawable.photo
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        viewPager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

        viewPager.setAdapter(mAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Adding Tabs
        for (int i=0;i<ICONS.length;i++) {

            actionBar.addTab(actionBar.newTab().setIcon(MainActivity.this.getResources().getDrawable(ICONS[i]))
                    .setTabListener(this));
        }

        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                // on changing the page
                // make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        });

    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        viewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {

    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {

    }
    public class TabsPagerAdapter extends FragmentPagerAdapter {

        public TabsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public android.support.v4.app.Fragment getItem(int index) {

            switch (index) {
                case 0:
                    return MixedFragment.newInstance();
                case 1:
                    return new VideosFragment();
                case 2:
                    return new AudioFragment();
                case 3:
                    return new TextFragment();
                case 4:
                    return new PictureFragment();
            }

            return null;
        }

        @Override
        public int getCount() {
            // get item count - equal to number of tabs
            return 5;
        }

    }
}

片段Class:

public class MixedFragment extends ListFragment implements AdapterView.OnItemClickListener {
    ListView mixed;
    JSONArray videos =null;
    List<NameValuePair> row;
    ArrayAdapter<VideoRow> adapter;

    private List<VideoRow> listRow = new ArrayList<>();
    private List<String> pathList = new ArrayList<>();


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.mixed, container, false);
        mixed = (ListView) v.findViewById(android.R.id.list);

        row = new ArrayList<>();

//        mixed.setOnItemClickListener(this);
        new populateLists().execute();
        return v;
    }

    public static MixedFragment newInstance(){

        MixedFragment mx = new MixedFragment();
        return mx;
    }



    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
        String sendPath = pathList.get(position);
        Intent start = new Intent(getActivity(), PlayVideo.class);
        start.putExtra("Path", sendPath);
        startActivity(start);
    }

    class populateLists extends AsyncTask<String,String,String> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

        }

        @Override
        protected String doInBackground(String... params) {


            JSONParser jParser = new JSONParser();
            JSONObject obj = jParser.makeHttpRequest(Config.URL_Populate,"GET",row);
            try {
                // Checking for SUCCESS TAG

                int success = obj.getInt("success");

                if (success == 1) {
                    // videos found
                    // Getting Array of videos
                    videos = obj.getJSONArray("video");

                    // looping through All videos
                    for (int i = 0; i < videos.length(); i++) {
                        JSONObject c = videos.getJSONObject(i);

                        // Storing each json item in variable
                        String path = Config.URL_2server+c.getString("path");
                        String thumbnail = c.getString("thumbnail");
                        String title = c.getString("title");
                        String name =c.getString("name");
                        title = "\""+title+"\"";

                        byte[] bytes = Base64.decode(thumbnail,Base64.DEFAULT);
                        Bitmap thumb = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                        pathList.add(path);
                        listRow.add(new VideoRow(path,thumb, name, title));

                    }
                }
                adapter = new MyListAdapterFrag(getActivity(), R.layout.enlarged_list_row, listRow,1);


            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }

        protected void onPostExecute(String file_url) {
            mixed.setAdapter(adapter);

        }
    }
}  

列表适配器:

public class MyListAdapterFrag extends ArrayAdapter<VideoRow> {
    List<VideoRow> lRow;
    Bitmap myThumb;
    int activity;

    public MyListAdapterFrag(Context context, int resource, List<VideoRow> listRow, int i) {
        super(context, resource, listRow);
        lRow=listRow;
        activity=i;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        View row = convertView;

        if (row == null) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            if (activity == 1) {
                row = inflater.inflate(R.layout.list_row, parent, false);
            } else if (activity == 2) {
                row = inflater.inflate(R.layout.enlarged_list_row, parent, false);
            }

            viewHolder = new ViewHolder();

            viewHolder.txtName = (TextView) row.findViewById(R.id.name);
            viewHolder.txtTitle = (TextView) row.findViewById(R.id.title);
            viewHolder.imageThumb = (ImageView) row.findViewById(R.id.thumbnail);

            row.setTag(viewHolder);

        } else {
            viewHolder = (ViewHolder) row.getTag();

        }
        VideoRow thisRow = lRow.get(position);

        viewHolder.txtName.setText(thisRow.getName());

        Bitmap thumb = thisRow.getThumb();
        if (activity == 1) {
            myThumb = Bitmap.createScaledBitmap(thumb, 40, 40, true);
        } else if (activity == 2) {
            myThumb = Bitmap.createScaledBitmap(thumb, 60, 60, true);
        }
        viewHolder.imageThumb.setImageBitmap(myThumb);

        viewHolder.txtTitle.setText(thisRow.getTitle());

        return row;
    }


    private static class ViewHolder {
        ImageView imageThumb;
        TextView txtTitle;
        TextView txtName;
    }
}

那么,你们知道是什么导致了这个错误吗?

当您移动到 ​​ViewPager 中的另一个片段时,前一个片段的视图可能会被破坏(我认为默认大小是两个片段,例如当片段#2 出现在屏幕上时,片段#0 被破坏)。当你回去时,它被重新创建。每次你从 return 到 MixedFragment 时,它的 onCreateView 方法都会被调用,但你永远不会在适配器被销毁时清除它。这就是您看到重复项的原因。

所以你可以在它的视图被销毁时清除适配器:

    @Override
    public void onDestroyView() {
      super.onDestroyView();
      adapter.clear();
    }

问题是由于当 ViewPager 超过某个点时您的片段被重新初始化。

这叫做off screen page limit

这意味着,一旦您的第一个 Fragment 超过限制,当您对它 return 时,将再次调用 onCreateView 函数。您需要检查 populateLists AsyncTask 是否真的需要触发。

或者,您可以增加屏幕外页面限制,以保留所有片段。