2015-04-28 1 views
0

Я создал ViewPager в своем MainActivity, который содержит 5 вкладок. На первой вкладке я поставил ListView для отображения некоторых элементов. Проблема в том, что всякий раз, когда я перебираю другую вкладку и возвращаюсь к первой, элементы в списке дублируются (список содержит A-B-C, а затем A-B-C-A-B-C). Странно, что это происходит только тогда, когда я прокручиваю дальше, чем вторая вкладка. Вот мой код:Android: Элементы FragmentList повторяются

MainActivity:

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; 
     } 

    } 
} 

Фрагмент Класс:

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); 

     } 
    } 
} 

ListAdapter:

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; 
    } 
} 

Итак, вы, ребята, знаете, что вызывает эту ошибку?

ответ

4

Проблема вызвана тем, что ваш фрагмент получает инициализируется, когда ViewPager проходит мимо определенной точки.

Это называется off screen page limit.

Это означает, что после того, как ваш первый фрагмент пройдет мимо предела, когда вы вернетесь к нему, функция onCreateView будет вызвана снова. Вам нужно проверить, действительно ли нужно активировать AyncTask populateLists или нет.

В качестве альтернативы вы можете увеличить лимит за пределами экрана, чтобы сохранить все ваши фрагменты.

+1

просто добавив viewPager.setOffscreenPageLimit (5) в MainActivity сделал трюк! Большое спасибо за ваш совет. – SoCo

4

Когда вы переходите к другому фрагменту в ViewPager, представление предыдущего фрагмента может быть уничтожено (я думаю, что размер по умолчанию - это два фрагмента, например, когда фрагмент №2 попадает на экран, фрагмент № 0 уничтожается). Когда вы вернетесь, он воссоздается. Каждый раз, когда вы возвращаетесь в MixedFragment, вызывается его метод onCreateView, но вы никогда не очищаете адаптер при его уничтожении. Вот почему вы видите дубликаты.

Таким образом, вы можете просто очистить адаптер, когда его вид разрушен:

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

Я пробовал ваше решение, и оно тоже работает! Большое спасибо за ваше время! – SoCo

+0

Помните, что setOffscreenPageLimit() со слишком большим количеством фрагментов может обременять вашу память. – inmyth