Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
410 views
in Technique[技术] by (71.8m points)

android - Unable to refresh listview data within same fragments used under different tabs

I have implemented tabs functionality via SmartTabLayout library in my android application. At present I have used same fragment as viewpager for both of my tabs. Since, the only difference is the view is that sorting of listitems. Below is my HomeActivity code:

HomeActivity.java

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

    final ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
    final SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab);
    viewPagerTab.setCustomTabView(this);

    FragmentPagerItems pages = new FragmentPagerItems(this);
    pages.add(FragmentPagerItem.of("Test1", SampleFragment.class));
    pages.add(FragmentPagerItem.of("Test2", SampleFragment.class));

    FragmentStatePagerItemAdapter adapter = new FragmentStatePagerItemAdapter(
            getSupportFragmentManager(), pages);

    viewPager.setAdapter(adapter);
    viewPager.setCurrentItem(0);
    viewPagerTab.setViewPager(viewPager);
}

@Override
public View createTabView(ViewGroup container, int position, PagerAdapter adapter) {
    LayoutInflater inflater = LayoutInflater.from(container.getContext());
    View tab = inflater.inflate(R.layout.custom_tab_icon_and_notification_mark, container, false);
    TextView txtTab=(TextView)tab.findViewById(R.id.txtTitle);
    switch (position){
        case 0:txtTab.setText("Test1");break;
        case 1:txtTab.setText("Test2");break;
        default:throw new IllegalStateException("Invalid pos - "+ position);
    }
    return tab;
}

My SampleFragment.java is as below wherein I do some server request for data and update the listview adapter.

SampleFragment.java

List<Items> lstItems=new ArrayList<>();
static ItemListAdapter mAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view= inflater.inflate(R.layout.fragment_sample, container, false);
    ListView lstviewItems = (ListView) view.findViewById(R.id.lstItems);
    int position = FragmentPagerItem.getPosition(getArguments());
    View emptyView=view.findViewById(R.id.emptyList);
    lstviewItems.setEmptyView(emptyView);
    mAdapter = new ItemsListAdapter(getActivity(),lstItems);
    lstviewItems.setAdapter(mAdapter);
    switch (position){
        case 0:
            //JsonObjectRequest
            loadItems();
            break;
        case 1:
            //sort the loaded items
            break;
    }
    return view;
}

private void loadItems(){
    try {
        JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET,url, null,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        lstItems.clear();
                        for (int i = 0; i < response.length(); i++) {
                            //Add item to lstItems
                        }
                        mAdapter.notifyDataSetChanged();
                    }
                }
        });
        testApp.getInstance().addToRequestQueue(request);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

But even after mAdapter.notifyDataSetChanged() the listview in the current viewPager tab i.e. Test1 tab is not getting refreshed. Whereas when I navigate to Test2 tab, I can see the changes in the listview, where is data has been loaded properly. Below is the screenshot for 2 different tabs.

Tabs

I've also searched for this problem and found other solution which did not work for me. One of the solution being, adding a refresh method in ItemsAdapter as below:

public void refresh(List<Items> items)
{
    this.items = items;
    notifyDataSetChanged();
}

and instead of mAdapter.notifyDataSetChanged() I used mAdapter.refresh(lstItems);. But unfortunately it did not work either. How can I possibly overcome this. Please let me know if I have to add furthermore details on this.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I think your problem is here:

mAdapter = new ItemsListAdapter(getActivity(),lstItems);

You create a new instance of ItemsListAdapter and bind it to the listview with

lstviewItems.setAdapter(mAdapter);

The problem is that this adapter is static. So if you create a new instance you destroy the old adapter and the listview of the other tab has not the adapter anymore that updates your data.

EDIT:

I'd recommend to load the data on a central place. Add the response (your data objects) to a manager class. Then implement on every view which using this data a callback (lets say JsonDataChangedCallback). Register the classes which implementing the callback to the manager with Manager.getInstance().registerCallback(). Then every time your data is changed call updateCallbacks() in your manager and all views will be updated. That's the way implemented that process in my app and it works.

Sample Code:

public class CDMMovieManager {
  private CDMMovieManager() {
    m_Movies = new ArrayList<>();
    m_MovieChangedCallbacks = new ArrayList<>();
  }

  public static synchronized CDMMovieManager getInstance() {
    if(ms_Instance == null)
      ms_Instance = new CDMMovieManager();

    return ms_Instance;
  }

  public void addMovie(CDMMovie p_Movie) {
    m_Movies.add(p_Movie);
    notifyCallbacks();
  }

  /**
   * Registers a movie changed callback
   *
   * @param p_MovieChangedCallback the callback to register
   */
  public void registerMovieChangedCallback(IDMMovieChangedCallback p_MovieChangedCallback) {
    m_MovieChangedCallbacks.add(p_MovieChangedCallback);
  }

  /**
   * Removes a movie changed callback
   *
   * @param p_MovieChangedCallback the callback to remove
   */
  public void removeMovieChangedCallback(IDMMovieChangedCallback p_MovieChangedCallback) {
    m_MovieChangedCallbacks.remove(p_MovieChangedCallback);
  }

  private void notifyCallbacks() {
    for(IDMMovieChangedCallback l_MovieChangedCallback : m_MovieChangedCallbacks) {
      l_MovieChangedCallback.onMoviesChanged();
    }
  }
}

And the implementing Class:

public class CDMBasicMovieFragment extends Fragment implements IDMMovieChangedCallback {

//...
  @Override
  public void onMoviesChanged() {
    m_Adapter.notifyDataSetChanged();
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...