mardi 5 janvier 2016

Android ListView not refreshing after dataset changed, though I have used the Adapter.notifyDataSetChanged()

I know similar questions had been asked here a couple of times, but none of them could help me with my problem, so I will just have to ask again.

What I have is an app that has a fragment that holds a ListView in the main activity and I used a PullableListView so that when I drag the ListView up, it will trigger the onLoadMore() callback method to load more data from the server. Once data loaded, the data will be saved to a SQLiteDB and then used by the ListView to show the updated data.

The is my PullableListViewFragment.java:

public class PullableListViewFragment extends Fragment implements
    OnItemClickListener {

private ListView listView;
private PullToRefreshLayout ptrl;

private MissionDB mMissionDB;
private List<MissionEntity> mData;

private MissionListAdapter mAdapter;

/**
 * Specify the exact mission that will be displayed in MissionDetailActivity
 */
private int mIndexOfMission;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View pullableLayout = inflater.inflate(R.layout.pullable_layout, container, false);
    listView = (ListView) pullableLayout.findViewById(R.id.content_view);
    listView.setDivider(null);
    ptrl = (PullToRefreshLayout) pullableLayout.findViewById(R.id.refresh_view);
    ptrl.setOnRefreshListener(new RefreshListener());
    loadData();

    Log.d(Constants.LOG_TAG, "onCreateView Called from PullableListViewFragment");

    return pullableLayout;
}

/**
 * Initialise ListView
 */
@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mAdapter = new MissionListAdapter(getActivity(), mData);
    listView.setAdapter(mAdapter);
    listView.setOnItemClickListener(this);
    mAdapter.notifyDataSetChanged();
    Log.d(Constants.LOG_TAG, "onActivityCreated Called from PullableListViewFragment");
}

/**
 * Load data from db
 */
private void loadData() {
    mData = new ArrayList<>();
    mMissionDB = MissionDB.getInstance(MyApplication.getContext());
    mData = mMissionDB.loadMission();
}

/**
 * OnItemClick event
 */
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
        long id) {
    Intent intent = new Intent(getActivity(), MissionDetailActivity.class);
    mIndexOfMission = mData.get((int) id).getId();
    intent.putExtra("Position", mIndexOfMission);
    startActivity(intent);
}

}

And this is the RefreshListener.java:

public class RefreshListener implements PullToRefreshLayout.OnRefreshListener {

private MissionDB mMissionDB = MissionDB.getInstance(MyApplication.getContext());

@Override
public void onLoadMore(final PullToRefreshLayout pullToRefreshLayout) {
    // LoadMore
    new Handler() {

        @Override
        public void handleMessage(Message msg) {

            /** When drag up, load more mission that is older and not out of date */
            mMissionDB.open();
            int id = mMissionDB.getMaxOrMinId("MIN");
            final JSONObject oldMission = new JSONObject();
            try {
                oldMission.put("platform", "1");
                oldMission.put("more", 0);
                oldMission.put("id", id);
                oldMission.put("size", 1);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            Thread t = new Thread(new Runnable() {

                @Override
                public void run() {
                    HttpRequest.sendHttpRequest(Constants.PULLORDRAG_TO_LOAD_MISSION_URL, oldMission, new HttpCallbackListener() {

                        @Override
                        public void onFinish(String response) {
                            MissionEntity mMission = new MissionEntity();

                            /** Save new mission to mission database */
                            try {
                                JSONObject jsonObject = new JSONObject(response);
                                JSONArray missionList = jsonObject.getJSONArray("taskList");
                                for (int i = 0; i < missionList.length(); i++) {
                                    JSONObject mission = missionList.getJSONObject(i);
                                    mMission.setId(mission.getInt("id"));
                                    mMission.setDownloadUrl(mission.getString("appPath"));
                                    mMission.setCreateTime(mission.getString("taskId"));
                                    mMission.setImageUrl(mission.getString("appImg"));
                                    mMission.setTitleName(mission.getString("appName"));
                                    mMission.setRemainTime("Remain: 1d 11h 23m 36s");
                                    mMission.setParticipant("135");
                                    mMission.setCreator("Google");
                                    mMission.setRequirement(mission.getString("description"));
                                    mMission.setRewards("TODO");
                                    mMission.setAttention("TODO");
                                    mMission.setValidDate(mission.getString("deadline"));
                                    mMission.setAccepted("0");
                                    mMission.setCollected("0");
                                    mMission.setAccomplished("0");
                                    mMissionDB.saveMission(mMission);
                                }
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onError(Exception e) {
                            e.printStackTrace();
                            Log.e(Constants.LOG_TAG, "Error while loading more");
                        }
                    });
                }
            });

            try {
                t.start();
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            pullToRefreshLayout.loadmoreFinish(PullToRefreshLayout.SUCCEED);
        }
    }.sendEmptyMessageDelayed(0, 1000);
}

}

The PullToRefreshLayout is a custom RelativeLayout that defined a inner interface OnRefreshListener that will be called once the onLoadMore() callback method is called.

The ListView I use in the Fragment is a PullableListView that implemented a Pullable interface that can drag up.

My Pullable.java:

public interface Pullable
{
    /**
     * If pull up is not needed, set canPullUp to false
     * 
     * @return true if the View can pull up
     */
    boolean canPullUp();
}

This is the fragment's layout.xml:

<LinearLayout xmlns:android="http://ift.tt/nIICcg"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="#f2f2f2"
          android:orientation="vertical">

<View
    android:layout_width="match_parent"
    android:layout_height="5dp" />

<pulltorefresh.PullToRefreshLayout
    android:id="@+id/refresh_view"
    android:layout_marginLeft="8dp"
    android:layout_marginRight="8dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/refresh_head"/>

    <!-- Supports all view that implemented the Pullable interface -->
    <pulltorefresh.PullableListView
        android:id="@+id/content_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <include layout="@layout/load_more"/>

</pulltorefresh.PullToRefreshLayout>

</LinearLayout>

The problem is when the data in the SQLiteDB is changed after the onLoadMore() method, the ListView in the fragment doesn't refresh itself unless I navigate to another fragment within the same main activity and then navigate back.

I tired all the ways I can find here and none of them help.

Could anyone tell me how can I make the ListView refresh itself when the data in the SQLiteDB changed.

Aucun commentaire:

Enregistrer un commentaire