【问题标题】:Reading stored data in offline mode在离线模式下读取存储的数据
【发布时间】:2016-09-30 10:49:22
【问题描述】:

在过去的 2 天里,我遇到了一个小问题。我先说明一下情况。我从我的服务器获取一些数据(当然是 JSON 对象),将它们存储在数据库中并在回收器视图中显示它们。

现在我想尝试一些有趣的事情。 Wifi关闭时应显示数据。我认为我不会有任何问题,因为数据是从 sqlite 数据库中读取的。但不知何故,在那种情况下,我的屏幕上什么也没有显示。

这是我的代码:

公告片段

public class AnnouncementsFragment extends Fragment {
public String titleForSQLite;
public String imageForSQLite;
public String articleForSQLite;
public static final String TAG = "AelApp";
private ArrayList<AnnouncementsModel> listItemsList;
private static final String IMAGE_URL = "http://www.theo-android.co.uk/ael/cms/announcement_images/";
AnnouncementsModel item;
RecyclerView myList;
AnnouncementsDatabaseHandler dba;
Context mContext;
private ArrayList<AnnouncementsModel> dbAnnouncements = new ArrayList<>();
private AnnouncementsAdapter announcementsAdapter;
public static final String ANNOUNCMENT_TAG = "ANNOUNCEMENT_FRAGMENT";
public AnnouncementsFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    getActivity().setTitle("Ανακοινώσεις");

    View rootView = inflater.inflate(R.layout.fragment_announcements, container, false);
    listItemsList = new ArrayList<>();


    dba = new AnnouncementsDatabaseHandler(getActivity());
    myList = (RecyclerView) rootView.findViewById(R.id.listview_announcements);

        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        myList.setHasFixedSize(true);
        myList.setLayoutManager(linearLayoutManager);
        announcementsAdapter = new AnnouncementsAdapter(getActivity(), listItemsList);
        myList.setAdapter(announcementsAdapter);


        updateAnnouncementsList();

        storingDataToSQlite();


    return rootView;
}


public void updateAnnouncementsList() {
    listItemsList.clear();


        // Instantiate the RequestQueue.
        RequestQueue queue = Volley.newRequestQueue(getActivity());

        // Request a string response from the provided URL.
        JsonArrayRequest jsObjRequest = new JsonArrayRequest(Request.Method.GET, URL.GET_ANNOUNCEMENTS, new Response.Listener<JSONArray>() {

            @Override
            public void onResponse(JSONArray response) {

                Log.d(TAG, response.toString());
                //hidePD();

                // Parse json data.
                // Declare the json objects that we need and then for loop through the children array.
                // Do the json parse in a try catch block to catch the exceptions
                try {

                    for (int i = 0; i < response.length(); i++) {

                        JSONObject post = response.getJSONObject(i);

                        item = new AnnouncementsModel();
                        item.setAnnouncement_title(post.getString("title"));
                        item.setAnnouncement_image(IMAGE_URL + post.getString("announcement_image"));
                        item.setAnnouncement_article(post.getString("article"));

                        listItemsList.add(item);

                        //Here I store the json strings.
                        titleForSQLite = post.getString("title");
                        imageForSQLite = post.getString("announcement_image");
                        articleForSQLite = post.getString("article");

                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                // Update list by notifying the adapter of changes
                announcementsAdapter.notifyDataSetChanged();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
                //hidePD();
            }
        });
        queue.add(jsObjRequest);

}
/*
* A method that add data in the SQlite database. It is found in AnnouncementsDatabaseHandler class
*/
public void storingDataToSQlite(){

    AnnouncementsModel myAnnouncements = new AnnouncementsModel();

    myAnnouncements.setAnnouncement_title(titleForSQLite);
    myAnnouncements.setAnnouncement_title(imageForSQLite);
    myAnnouncements.setAnnouncement_article(articleForSQLite);

    dba.addAnnouncements(myAnnouncements);
    fetchDataFromDB();
    dba.close();

}
/*
* A method that reads data from the database. It is found in AnnouncementsDatabaseHandler class
*/
public void fetchDataFromDB() {

    ArrayList<AnnouncementsModel> membersDB = dba.getAnnouncements();

    for(int i=0; i<membersDB.size();i++){
        String id = membersDB.get(i).getAnnouncement_id();
        String mTitle = membersDB.get(i).getAnnouncement_title();
        String mArticle = membersDB.get(i).getAnnouncement_article();

        String image = membersDB.get(i).getAnnouncement_image();

        AnnouncementsModel f = new AnnouncementsModel();

        f.setAnnouncement_id(id);
        f.setAnnouncement_title(mTitle);
        f.setAnnouncement_article(mArticle);
        f.setAnnouncement_image(image);

        dbAnnouncements.add(f);

    }
    dba.close();
  }
}

在我的 webservice 方法中,我从响应中提取 json 字符串。(也许我应该从 ArrayList 中读取字符串?)

                        //Here I store the json strings.
                        titleForSQLite = post.getString("title");
                        imageForSQLite = post.getString("announcement_image");
                        articleForSQLite = post.getString("article");

接下来我在数据库中添加titleForSQLite,imageForSQLite,articleForSQLite。

 public void storingDataToSQlite(){

    AnnouncementsModel myAnnouncements = new AnnouncementsModel();

    myAnnouncements.setAnnouncement_title(titleForSQLite);
    myAnnouncements.setAnnouncement_title(imageForSQLite);
    myAnnouncements.setAnnouncement_article(articleForSQLite);

    dba.addAnnouncements(myAnnouncements);
    fetchDataFromDB();
    dba.close();

}

最后我读了它们

public void fetchDataFromDB() {

    ArrayList<AnnouncementsModel> membersDB = dba.getAnnouncements();

    for(int i=0; i<membersDB.size();i++){
        String id = membersDB.get(i).getAnnouncement_id();
        String mTitle = membersDB.get(i).getAnnouncement_title();
        String mArticle = membersDB.get(i).getAnnouncement_article();

        String image = membersDB.get(i).getAnnouncement_image();

        AnnouncementsModel f = new AnnouncementsModel();

        f.setAnnouncement_id(id);
        f.setAnnouncement_title(mTitle);
        f.setAnnouncement_article(mArticle);
        f.setAnnouncement_image(image);

        dbAnnouncements.add(f);

    }
    dba.close();
}

那么为什么我会遇到我之前描述的问题?由于所有内容都存储在数据库中,因此数据应该在打开和关闭 wifi 的情况下读取,对吧?有什么想法吗?

这是我的 sqlite 数据库代码。

public class AnnouncementsDatabaseHandler extends SQLiteOpenHelper {

private final ArrayList<AnnouncementsModel> announcementsModelArrayList = new ArrayList<>();

public AnnouncementsDatabaseHandler(Context context) {
    super(context, Constants.DATABASE_NAME, null, Constants.DATABASE_VERSION);
}
/*
* This callback method creates the database
*/
@Override
public void onCreate(SQLiteDatabase db) {

    String CREATE_ANNOUNCEMENTS_TABLE = "CREATE TABLE IF NOT EXISTS " + AnnouncementsConstants.TABLE_NAME +
            "(" + AnnouncementsConstants.KEY_ID + " INTEGER PRIMARY KEY, " + AnnouncementsConstants.ANNOUNCEMENT_TITLE+
            " TEXT, "  +  AnnouncementsConstants.ANNOUNCEMENT_image + " TEXT, " + AnnouncementsConstants.ANNOUNCEMENT_article + " TEXT);";



    db.execSQL(CREATE_ANNOUNCEMENTS_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
    db.execSQL("DROP TABLE IF EXISTS " + AnnouncementsConstants.TABLE_NAME);

    onCreate(db);
}
/*
*Add contents to table. Those contents are json strings that
*are retrieved from the server!
*/
public void addAnnouncements(AnnouncementsModel announcementsModel) {
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(AnnouncementsConstants.KEY_ID,announcementsModel.getAnnouncement_id());
    values.put(AnnouncementsConstants.ANNOUNCEMENT_article, announcementsModel.getAnnouncement_title());
    values.put(AnnouncementsConstants.ANNOUNCEMENT_image, announcementsModel.getAnnouncement_title());
    values.put(AnnouncementsConstants.ANNOUNCEMENT_article, announcementsModel.getAnnouncement_article());


    db.insertWithOnConflict(AnnouncementsConstants.TABLE_NAME, AnnouncementsConstants.KEY_ID, values,
            SQLiteDatabase.CONFLICT_REPLACE);
    db.close();

    Log.d("Theo", "heeeey!data saved");
}
/*
* This method allows to read the stored data,and returns an
* array list.
*/
public ArrayList<AnnouncementsModel> getAnnouncements() {

    String select_query = "SELECT * " + AnnouncementsConstants.TABLE_NAME;

    SQLiteDatabase db = this.getReadableDatabase();

    Cursor cursor = db.query(Constants.TABLE_NAME, new String[]{
                    AnnouncementsConstants.KEY_ID, AnnouncementsConstants.ANNOUNCEMENT_TITLE, AnnouncementsConstants.ANNOUNCEMENT_article
            ,AnnouncementsConstants.ANNOUNCEMENT_image}, null, null, null, null,
            Constants.KEY_ID + " DESC");

    if (cursor.moveToFirst()) {
        do {

            AnnouncementsModel m = new AnnouncementsModel();
            m.setAnnouncement_title(cursor.getString(cursor.getColumnIndex(AnnouncementsConstants.ANNOUNCEMENT_TITLE)));
            m.setAnnouncement_image(cursor.getString(cursor.getColumnIndex(AnnouncementsConstants.ANNOUNCEMENT_image)));
            m.setAnnouncement_article(cursor.getString(cursor.getColumnIndex(AnnouncementsConstants.ANNOUNCEMENT_article)));
            m.setAnnouncement_id(cursor.getString(cursor.getColumnIndex(AnnouncementsConstants.KEY_ID)));


            announcementsModelArrayList.add(m);
        }while(cursor.moveToNext());


    }
    return announcementsModelArrayList;
} 

谢谢,

西奥。

【问题讨论】:

  • 您如何检查数据是否存储在数据库中?..您可以分享您编写的存储在数据库中的代码
  • 是的,数据已存储。
  • 我把你问的代码,反正。

标签: java android json sqlite


【解决方案1】:
  1. 一个问题是,titleForSQLite、imageForSQLite、articleForSQLite 值仅填充数据流中的最后一个值,因为它们位于 for 循环中。
  2. 检查您的 dba 对象是否已准备好读写数据库。

【讨论】:

  • 我在想你在说什么。但不知道如何继续。
  • 在您的 storageDataToSQlite() 方法中,您只存储一个 AnnouncementsModel 对象值。但是您正在从 json 响应中解析一个数组列表,并从数据库中获取数组列表。为什么会这样?
  • 哦,所以我应该将整个 Arraylist 数据存储在 storageDataToSQlite() 方法中,对吧?
  • 是的。现在您只存储最后一个值。
  • 这样的? AnnouncementsModel myAnnouncements = new AnnouncementsModel(); listItemsList.add(myAnnouncements); dba.addAnnouncements(myAnnouncements); dba.close();
【解决方案2】:

我认为你的选择查询是错误的

应该是

String select_query = "SELECT * from " + AnnouncementsConstants.TABLE_NAME;

从服务器接收到数据后,调用下面的方法表单进行循环

存储数据ToSQlite();

和 fetchDataFromDB();在 for 循环结束后......或者如果数据已经存在,您也可以从 oncreate 调用此方法

在 Oncreate 中添加以下代码

if(isOnline)
{
  // get data from server
}else{
  // fetch data from db
}

【讨论】:

  • 我使用 Cursor cursor = db.query(Constants.TABLE_NAME, new String[]{ AnnouncementsConstants.KEY_ID, AnnouncementsConstants.ANNOUNCEMENT_TITLE, AnnouncementsConstants.ANNOUNCEMENT_article ,AnnouncementsConstants.ANNOUNCEMENT_image}, null, null, null, null, 常量.KEY_ID + "DESC");
  • 不需要 String select_query 读取操作。
  • 它对我的问题没有任何作用。
  • //这里存放的是json字符串。 titleForSQLite = post.getString("title"); imageForSQLite = post.getString("announcement_image"); articleForSQLite = post.getString("article"); storageDataToSQlite(); } fetchDataFromDB();
  • 所以我应该让 web 服务只在 wifi 开启时运行:)
猜你喜欢
  • 2018-10-13
  • 1970-01-01
  • 2012-03-06
  • 2016-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多