Android ListView not refreshing after dataset changed, though I have used the Adapter.notifyDataSetChanged()
<p>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.</p>

<p>What I have is an app that has a fragment that holds a ListView in the main activity and I used a <strong>PullableListView</strong> so that when I drag the ListView up, it will trigger the <strong>onLoadMore()</strong>  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. </p>

<p>The is my PullableListViewFragment.java:</p>

<pre><code>public class PullableListViewFragment extends Fragment implements
    OnItemClickListener {

private ListView listView;
private PullToRefreshLayout ptrl;

private MissionDB mMissionDB;
private List&lt;MissionEntity&gt; 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&lt;&gt;();
    mMissionDB = MissionDB.getInstance(MyApplication.getContext());
    mData = mMissionDB.loadMission();
}

/**
 * OnItemClick event
 */
@Override
public void onItemClick(AdapterView&lt;?&gt; 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);
}

}
</code></pre>

<p>And this is the RefreshListener.java:</p>

<pre><code>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 &lt; 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);

            //==================Update 1==================
            ListView list = (ListView) pullToRefreshLayout.findViewById(R.id.content_view);
            List&lt;MissionEntity&gt; missionList = mMissionDB.loadMission();
            Log.d(Constants.LOG_TAG, "mission size" + missionList.size());
            MissionListAdapter adapter = (MissionListAdapter) list.getAdapter();
            adapter.setData(missionList);
            adapter.notifyDataSetChanged();
            list.setAdapter(adapter);
            //==================Update 1==================
        }
    }.sendEmptyMessageDelayed(0, 1000);
}

}
</code></pre>

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

<p>The ListView I use in the Fragment is a <strong>PullableListView</strong> that implemented a <strong>Pullable</strong> interface that can drag up.</p>

<p>My Pullable.java:</p>

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

<p>This is the fragment's layout.xml:</p>

<pre><code>&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="#f2f2f2"
          android:orientation="vertical"&gt;

&lt;View
    android:layout_width="match_parent"
    android:layout_height="5dp" /&gt;

&lt;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"&gt;

    &lt;include layout="@layout/refresh_head"/&gt;

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

    &lt;include layout="@layout/load_more"/&gt;

&lt;/pulltorefresh.PullToRefreshLayout&gt;

&lt;/LinearLayout&gt;
</code></pre>

<p>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.</p>

<p>I tired all the ways I can find here and none of them help. </p>

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

<p><strong>[Update 1]</strong> I've added some code in the onLoadMore() callback, the size of the data remains the same after I get some data from the server, i think this is the problem why the ListVie is not refreshing, what's interesting is if I put a <code>Thread.sleep(500)</code> before <code>mMission.loadMission()</code> the size of the data is correct and everything is fine. Any idea why?</p>