虽然我使用了Adapter.notifyDataSetChanged(),但在更改数据集后Android ListView没有刷新

时间:2016-01-06 02:23:36

标签: java android sqlite android-listview

我知道这里曾经问过几次类似的问题,但是没有一个能帮我解决问题,所以我只能再问一次。

我所拥有的应用程序有一个片段,在主活动中包含ListView,我使用了 PullableListView ,这样当我向上拖动ListView时,它将触发 onLoadMore ()回调方法从服务器加载更多数据。加载数据后,数据将保存到SQLiteDB,然后由ListView用于显示更新的数据。

是我的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);
}

}

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

            //==================Update 1==================
            ListView list = (ListView) pullToRefreshLayout.findViewById(R.id.content_view);
            List<MissionEntity> 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);
}

}

PullToRefreshLayout是一个自定义RelativeLayout,它定义了一个内部接口 OnRefreshListener ,一旦调用了 onLoadMore()回调方法,就会调用它。

我在Fragment中使用的ListView是一个 PullableListView ,它实现了一个可以拖动的 Pullable 界面。

我的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();
}

这是片段的layout.xml:

<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">

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

问题是在onLoadMore()方法之后更改SQLiteDB中的数据时,片段中的ListView不会自行刷新,除非我导航到同一主活动中的另一个片段然后导航回来。 / p>

我厌倦了我在这里找到的所有方式,但没有一方能帮助我。

有人能告诉我当SQLiteDB中的数据发生变化时,如何让ListView自行刷新。

[更新1] 我在onLoadMore()回调中添加了一些代码,从服务器获取一些数据后数据的大小保持不变,我认为这是这个问题为什么ListVie没有刷新,有趣的是,如果我在Thread.sleep(500)之前放置mMission.loadMission()数据的大小是正确的,一切都很好。知道为什么吗?

2 个答案:

答案 0 :(得分:1)

在onLoadMore方法中,您只需加载数据并保存到数据库中。加载数据后,您应该更新适配器的数据源并调用adapter.notifyDataSetChanged()来刷新列表视图。或者您可以通知片段从数据库重新加载数据。

答案 1 :(得分:1)

确保在首次加载时获取数据。而且我认为你的mMissionDB确实发生了变化,但是mData呢?您的适配器实际上使用mData作为数据源,因此您应该更新mData,并调用 adapter.notifyDataSetChanged()来刷新列表视图。希望它可以帮到你。