【问题标题】:How to save RSS feed data into SQLite in Android?如何将 RSS 提要数据保存到 Android 中的 SQLite?
【发布时间】:2022-01-29 06:45:18
【问题描述】:

我能够在 android studio 中成功解析 RSS 提要,但我想将解析后的数据保存到数据库中,所以如果我离线,我仍然可以从保存的数据中检索。

这是我的MainActivity

package com.jjurrius.simplerssvideo;

import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    ListView lvRss;
    ArrayList<String> titles;
    ArrayList<String> links;
    private DatabaseHandler db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lvRss = (ListView) findViewById(R.id.lvRss);

        titles = new ArrayList<String>();
        links = new ArrayList<String>();
        db = new DatabaseHandler(this);

        try {
            db.open();
            NewsInformation item = new NewsInformation();
            item.completeTextLink = "Your Link of news";
            item.title            = "title of news";
            item.writerName       = "writer of news";
            item.dateWriten       = "1999";
            item.source           = "something";
            item.smallBody        = "news body";
            item.bigBody          = "news text";
            item.page             = "1";
            db.insertNewsInfo(item);
            db.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }


        lvRss.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                Uri uri = Uri.parse(links.get(position));
                Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                startActivity(intent);
            }
        });

        new ProcessInBackground().execute();
    }

    public InputStream getInputStream(URL url)
    {
        try
        {
            return url.openConnection().getInputStream();
        }
        catch (IOException e)
        {
            return null;
        }
    }

    public class ProcessInBackground extends AsyncTask<Integer, Void, Exception>
    {
        ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);

        Exception exception = null;
        @Override
        protected void onPreExecute() {
            progressDialog.setMessage("Fetching Latest News!");
            progressDialog.show();

        }

        @Override
        protected Exception doInBackground(Integer... integers) {
            try
            {

                // rss feed site here
                URL url = new URL("https://moxie.foxnews.com/feedburner/world.xml");
                // factory new instance
                XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
                factory.setNamespaceAware(false);
                XmlPullParser xpp = factory.newPullParser();
                xpp.setInput(getInputStream(url),"UTF_8");

                boolean insideItem = false;

                int eventType = xpp.getEventType();

                while (eventType != XmlPullParser.END_DOCUMENT)
                {
                    if(eventType == XmlPullParser.START_TAG)
                    {
                        if(xpp.getName().equalsIgnoreCase("item"))
                        {
                            insideItem = true;
                        }
                        else if (xpp.getName().equalsIgnoreCase("title"))
                        {
                            if(insideItem)
                            {
                                titles.add(xpp.nextText());

                            }
                        }

                    }
                    else if(eventType == XmlPullParser.START_TAG && xpp.getName().equalsIgnoreCase("item"))
                    {
                        insideItem = false;
                    }

                    eventType = xpp.next();
                }
            }
            catch (MalformedURLException e)
            {
                exception = e;
            }
            catch (XmlPullParserException e)
            {
                exception = e;
            }
            catch (IOException e)
            {
                exception = e;
            }
            return null;
        }

        @Override
        protected void onPostExecute(Exception s) {
            super.onPostExecute(s);

            ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,titles);

            lvRss.setAdapter(adapter);
            progressDialog.dismiss();

        }
    }
}

我的NewsInformation.java

package com.jjurrius.simplerssvideo;

public class NewsInformation
{
    public String completeTextLink;
    public String title;
    public String writerName;
    public String dateWriten;
    public String source;
    public String smallBody;
    public String bigBody;
    public String page;
}

我的DabaseHelper.java

package com.jjurrius.simplerssvideo;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class DatabaseHelper extends SQLiteOpenHelper {

    private final String TAG = "DatabaseHelper";
    private static final String DATABASE_NAME = "db_for_news";

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, 10);

        //fdd
        Log.i(TAG, "Object created.");
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE news ( page TEXT ," +
                " completeTextLink TEXT  ,title TEXT , writerName TEXT , dateWriten TEXT ," +
                " source TEXT ,  smallBody TEXT , bigBody TEXT);");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(DatabaseHelper.class.getName(), "Upgrading database from version "
                + oldVersion + " to " + newVersion + ", which will destroy all old data");
        db.execSQL("Drop table if exists news" );
        onCreate(db);
    }
}

我的DatabaseHandler.java

package com.jjurrius.simplerssvideo;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DatabaseHandler {

    private DatabaseHelper dbHelper;
    private SQLiteDatabase database;


    public DatabaseHandler(Context context) {
        dbHelper = new DatabaseHelper(context);
    }

    //methods for all table
    public void open() throws SQLException {
        database = dbHelper.getWritableDatabase();
    }

    public void close() {
        dbHelper.close();
    }

    public void clearTable(String tableName) {
        database.delete( tableName, null, null);
    }

    //news table method

    public void insertNewsInfo(NewsInformation newsInfo) {
        ContentValues cv = new ContentValues();
        cv.put("bigBody"          ,  newsInfo.bigBody );
        cv.put("completeTextLink" ,  newsInfo.completeTextLink );
        cv.put("dateWriten"       ,  newsInfo.dateWriten );
        cv.put("source"            ,  newsInfo.source );
        cv.put("smallBody"        ,  newsInfo.smallBody );
        cv.put("title"            ,  newsInfo.title );
        cv.put("writerName"       ,  newsInfo.writerName );
        cv.put("page"             ,  newsInfo.page );

        database.insert("news" , "writerName", cv);
    }


    public List<NewsInformation> getAllNewsForPage(String page) {
        List<NewsInformation> NewsInfoList = new ArrayList<NewsInformation>();

        Cursor cursor = database.rawQuery("select completeTextLink " +
                " , title , writerName , dateWriten , source , smallBody , bigBody" +
                " FROM news where page = ?", new String[]{page});


        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            NewsInformation newsInfo = new NewsInformation();

            newsInfo.completeTextLink = cursor.getString(0);
            newsInfo.title = cursor.getString(1);
            newsInfo.writerName = cursor.getString(2);
            newsInfo.dateWriten = cursor.getString(3);
            newsInfo.source = cursor.getString(4);
            newsInfo.smallBody = cursor.getString(5);
            newsInfo.bigBody = cursor.getString(6);
            newsInfo.page = page;

            NewsInfoList.add(newsInfo);
            cursor.moveToNext();
        }

        // Make sure to close the cursor
        cursor.close();

        return NewsInfoList;
    }

    public String getBigBody(String completeBodyLink) {
        Cursor cursor = database.rawQuery("select bigBody FROM news where completeTextLink = ?", new String[]{completeBodyLink});
        cursor.moveToFirst();
        String bigBody = cursor.getString(0);
        cursor.close();
        return bigBody;
    }
}

当我运行该应用程序时,它会向我显示 rss 提要,但我无法保存它们。我不知道错误在哪里。

这是我的 github 仓库:SimpleRssFeed

【问题讨论】:

    标签: java android sqlite xml-parsing


    【解决方案1】:

    你好,我的朋友; 我更改了您的代码,为了更好地理解,我使用 DocumentElementNodeList 对象来获取 Rss。 在 doInBackground 方法中,我们获取 rss 中的所有必需字段并创建 NewsInformation 对象,最后我们得到 NewsInformation 列表,并在 onPostExecute 方法中将它们添加到 DB 和 Listview 适配器, 这是我对您的代码所做的更改:

    您的数据对象

        public class NewsInformation
    {
        public String link;
        public String title;
        public String pubdate;
        public String category;
    
    }
    

    和您的活动:

        import android.app.ProgressDialog;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.AsyncTask;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.sql.SQLException;
    import java.util.ArrayList;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    public class RssReader extends AppCompatActivity {
    
        ListView lvRss;
        ArrayList<String> titles;
        ArrayList<String> links;
        ArrayList<NewsInformation> news =new ArrayList<>();
        private DatabaseHandler db;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.rss_reader);
            lvRss = (ListView) findViewById(R.id.lvRss);
    
            titles = new ArrayList<String>();
            links = new ArrayList<String>();
            db = new DatabaseHandler(this);
    
    
            lvRss.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                    Uri uri = Uri.parse(links.get(position));
                    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                    startActivity(intent);
                }
            });
    
            new ProcessInBackground().execute();
        }
    
        public InputStream getInputStream(URL url) {
            try {
                return url.openConnection().getInputStream();
            } catch (IOException e) {
                return null;
            }
        }
    
        public class ProcessInBackground extends AsyncTask<Integer, Void, Exception> {
            ProgressDialog progressDialog = new ProgressDialog(RssReader.this);
    
            Exception exception = null;
    
            @Override
            protected void onPreExecute() {
                progressDialog.setMessage("Fetching Latest News!");
                progressDialog.show();
    
            }
    
            @Override
            protected Exception doInBackground(Integer... integers) {
                try {
                    // rss feed site here
                    URL url = new URL("https://moxie.foxnews.com/feedburner/world.xml");
    
                    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                    DocumentBuilder db = dbf.newDocumentBuilder();
    
                    Document doc = db.parse(getInputStream(url));
    
                    doc.getDocumentElement().normalize();
                    NodeList nodeList = doc.getElementsByTagName("item");
                    Log.e("node size:", String.valueOf(nodeList.getLength()));
                    //// fetch every node item in RSS and create news_item list
                    for (int i = 0; i < nodeList.getLength(); i++) {
                        NewsInformation news_item = new NewsInformation();
                        Node node = nodeList.item(i);
                        Element parentItem = (Element) node;
    
                        NodeList links = parentItem.getElementsByTagName("link");
                        Element element_link = (Element) links.item(0);
                        NodeList element_link_childNodes = element_link.getChildNodes();
                        news_item.link = element_link_childNodes.item(0).getNodeValue();
    
    
                        NodeList titles = parentItem.getElementsByTagName("title");
                        Element element_title = (Element) titles.item(0);
                        NodeList element_title_childNodes = element_title.getChildNodes();
                        news_item.title = element_title_childNodes.item(0).getNodeValue();
    
    
                        NodeList pubDates = parentItem.getElementsByTagName("pubDate");
                        Element element_pubDate = (Element) pubDates.item(0);
                        NodeList element_pubDate_childNodes = element_pubDate.getChildNodes();
                        news_item.pubdate = element_pubDate_childNodes.item(0).getNodeValue();
    
    
                        NodeList categorys = parentItem.getElementsByTagName("pubDate");
                        Element element_category = (Element) categorys.item(0);
                        NodeList element_category_childNodes = element_category.getChildNodes();
                        news_item.category = element_category_childNodes.item(0).getNodeValue();
    
                        news.add(news_item);
    
                       //////////////////////////////////////////////////////////////////////////////////////////////
    
                    }
    
    
                } catch (MalformedURLException e) {
                    exception = e;
                    Log.e("nerror1:", String.valueOf(e));
                } catch (IOException e) {
                    exception = e;
                    Log.e("nerror2:", String.valueOf(e));
                } catch (ParserConfigurationException e) {
                    e.printStackTrace();
                    Log.e("nerror3:", String.valueOf(e));
                } catch (SAXException e) {
                    e.printStackTrace();
                    Log.e("nerror4:", String.valueOf(e));
                }
                return null;
            }
    
            @Override
            protected void onPostExecute(Exception s) {
                super.onPostExecute(s);
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(RssReader.this, android.R.layout.simple_list_item_1, titles);
                lvRss.setAdapter(adapter);
    
    //////////// after fetching data insert to db///////////////////////////////////////////
                    try {
                        db.open();
                        for (int i = 0; i < news.size(); ++i) {
                            db.insertNewsInfo(news.get(i));
                        }
                        db.close();
    
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }
    
    /////////////////////////////////////////////////////////////////////////////
                progressDialog.dismiss();
    
            }
        }
    }
    

    作为建议,我向您推荐:

    • 使用协程库而不是 AsyncTask 类(阅读协程)

    • 对于 http/https 请求使用改造库

    • 使用 Room 代替 dataBaseHandler

    【讨论】:

    • 什么是 rss_reader 布局?我应该创建一个吗?
    • 不,那是你的xml布局没有改变,只是改变文件名
    • 好吧,让我试试。第一次尝试不成功。 RssReader 是 MainActivity?你有回购什么的吗?
    • 是的,它是mainactivity尝试然后给我分数:))搜索关键字有很多关于它们的文档,官方网站android也可以
    • 你测试过代码吗?它在您的本地环境中工作吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多