【问题标题】:Store JSON Array from NewsAPI in Firebase在 Firebase 中存储来自 NewsAPI 的 JSON 数组
【发布时间】:2018-02-03 13:48:13
【问题描述】:

我使用 volley 来解析来自 newsAPI.org 的新闻数据。我想将响应保存到 Firebase 以供离线查看和持久化。

这是来自 API 的示例响应:

articles: [
{
     author: "Megan Rose Dickey",
     title: "Ojo wants to be the electric scooter for commuters, but...",
     description: "Commuting in a busy city like San Francisco can be 
     annoying..",
     url: "https://techcrunch.com/2017/08/23/ojo-wants-to-be-the-electric-
     scooter-for-commuters-but-its-not-there-yet/",
     urlToImage: "https://img.vidible.tv/prod/2017",
     publishedAt: "2017-08-23T21:19:56Z"
},
{
     author: "Katie Roof",
     title: "Pishevar intervenes in Benchmark-Kalanick lawsuit",
     description: "Early Uber investor and former board member Shervin 
     Pishevar is speaking out against Benchmark again..",
     url: "https://techcrunch.com/2017/08/24/pishevar-sends-another-letter-
     to-uber-board-about-benchmark/",
     urlToImage:"https://tctechcrunch2011.files.wordpress.com/",
     publishedAt: "2017-08-24T22:49:59Z"
},

articles 数组中总共有 5 个对象。 我想将每个对象存储在 Firebase 数据库中。这是我尝试过的:

StringRequest stringRequest = new StringRequest(Request.Method.GET, Constants.NEWS_ENDPOINT,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    if (response != null){
                        Log.d(TAG, "News Api Response is: \t" + response.toString());
                        try {
                            JSONObject jsonObject = new JSONObject(response);
                            JSONArray articles = jsonObject.getJSONArray("articles");
                            for (int i = 0; i < articles.length(); i++){
                                JSONObject items = articles.getJSONObject(i);

                                final String title_news = items.getString("title");
                                final String desc_news = items.getString("description");
                                final String urlImg = items.getString("urlToImage");
                                final String author_news = items.getString("author");
                                final String url = items.getString("url");
                                final String publishedAt = items.getString("publishedAt");

                                NewsItem newsItem = new NewsItem(author_news, title_news, desc_news, url, urlImg, publishedAt);
                                itemList.add(newsItem);

                                /**
                                 *  Save JSON Results to Firebase
                                 * */

                                for (int k = 0; k < articles.length(); k++){
                                    HashMap hashMap = new HashMap();

                                    hashMap.put("newsTitle", title_news);
                                    hashMap.put("newsDesc", desc_news);
                                    hashMap.put("newsImageUrl", urlImg);
                                    hashMap.put("newsAuthor", author_news);
                                    hashMap.put("newsUrl", url);
                                    hashMap.put("newsDate", publishedAt);

                                    newsRootRef.setValue(hashMap);
                                }

当我检查控制台时,它只保存一个对象,最后一个对象是这样的:

我想将所有对象按原样存储在响应数组中并稍后检索它们。还有其他方法可以做到这一点吗?谢谢,很抱歉发了这么长的帖子。

【问题讨论】:

    标签: arrays json firebase firebase-realtime-database android-volley


    【解决方案1】:

    在这种情况下,您需要使用 push() 来存储数据。否则,您只是在每次迭代时替换引用处的数据。这就是为什么似乎只存储最后一条记录的原因。尝试更改此行:

    newsRootRef.setValue(hashMap);
    

    ...进入这个:

    newsRootRef.push().setValue(hashMap);
    

    为避免重复条目,我建议您从 Firebase 获取所有条目并将 url 属性(因为该属性似乎是唯一的)缓存在 HashSet 中。然后你可以像这样修改你的代码:

    if (!urlSet.contains(url)) {
        HashMap hashMap = new HashMap();
        hashMap.put("newsTitle", title_news);
        hashMap.put("newsDesc", desc_news);
        hashMap.put("newsImageUrl", urlImg);
        hashMap.put("newsAuthor", author_news);
        hashMap.put("newsUrl", url);
        hashMap.put("newsDate", publishedAt);
        newsRootRef.push(),setValue(hashMap);
    }
    

    当然,您需要先填充 HashSet,所以我建议您这样做:

        final Set<String> urlSet = new HashSet<>();
    
        newsRootRef.addChildEventListener(new ChildEventListener() {
            int i = 0;
    
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
    
                urlSet.add(dataSnapshot.getValue(String.class));
                if (i++ == dataSnapshot.getChildrenCount()) {
    
                    ...
                    ...your code...
                    StringRequest stringRequest = new StringRequest(Request.Method.GET, Constants.NEWS_ENDPOINT,
                            new Response.Listener<String>() {
                                @Override
                                public void onResponse(String response) {
    
                    ...
                    ...
    
                }
    
            }
    
            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            }
    
            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
            }
    
            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {
            }
    
            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        });
    

    【讨论】:

    • 谢谢兄弟@Henrik Enblom
    • 它现在只有一个小问题,当我从列表中打开一篇文章并返回主屏幕时,数据库值在 firebase 控制台中重复。如何只保留一份副本?
    • 没问题!我已经更新了我的答案,向您展示如何避免这种情况。您介意将我的答案标记为“正确”吗?
    • 兄弟,我接受了你的回答。这就是我认为的问题所在 - 当我访问列表中的新闻项目时,我会被定向到 NewsDetailsActivity。按下后退按钮后,网络调用再次执行,请求被重新保存到 Firebase。你的代码很优雅,谢谢。你能告诉我当我点击后退按钮时如何避免发出另一个网络请求吗?再次感谢。
    • 谢谢你!我建议查看此页面:firebase.google.com/docs/database/android/offline-capabilities,尤其是 FirebaseDatabase.getInstance().setPersistenceEnabled(true);在这种特殊情况下,我可能会使用某种宽限期来下载新闻流。例如,仅在自上次更新后超过十分钟时才更新流。
    猜你喜欢
    • 2019-01-21
    • 2020-08-01
    • 2020-05-31
    • 1970-01-01
    • 2017-01-25
    • 2018-07-05
    • 1970-01-01
    • 2021-01-18
    • 1970-01-01
    相关资源
    最近更新 更多