我知道这里曾经问过几次类似的问题,但是没有一个能帮我解决问题,所以我只能再问一次。
我所拥有的应用程序有一个片段,在主活动中包含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()
数据的大小是正确的,一切都很好。知道为什么吗?
答案 0 :(得分:1)
在onLoadMore方法中,您只需加载数据并保存到数据库中。加载数据后,您应该更新适配器的数据源并调用adapter.notifyDataSetChanged()来刷新列表视图。或者您可以通知片段从数据库重新加载数据。
答案 1 :(得分:1)
确保在首次加载时获取数据。而且我认为你的mMissionDB确实发生了变化,但是mData呢?您的适配器实际上使用mData作为数据源,因此您应该更新mData,并调用 adapter.notifyDataSetChanged()来刷新列表视图。希望它可以帮到你。