如何使用“标题”更新列表视图

Posted

技术标签:

【中文标题】如何使用“标题”更新列表视图【英文标题】:How to update list view with 'titles' 【发布时间】:2019-12-07 20:40:51 【问题描述】:

我正在尝试按照 Udemy“完整的 android N 开发人员课程”实施新闻阅读器应用程序。使用了列表视图。

按照我正确遵循的说明,但在执行以下主要活动时,虽然需要更新带有标题的列表项,但在列表视图中没有显示任何内容。即使在 Android 监视器中也没有错误。

请提供任何有关查找问题的建议。

谢谢!

public class MainActivity extends AppCompatActivity 

    ArrayList<String > titles = new ArrayList<>();
    ArrayList<String> content = new ArrayList<>();
    ArrayAdapter arrayAdapter;
    SQLiteDatabase articleDB ;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(R.id.listView );
        arrayAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,titles);
        listView.setAdapter(arrayAdapter);
        articleDB = this.openOrCreateDatabase("articles",MODE_PRIVATE,null);
        articleDB.execSQL("CREATE TABLE IF NOT EXISTS articles (id INTEGER PRIMARY KEY, articleID INTEGER,title VARCHAR,content VARCHAR)");
        updateListView();
        DownloadTask task = new DownloadTask();
        try 
            task.execute("https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty");
        catch(Exception e)
           e.printStackTrace();
        
    
    //update table
    public void updateListView()
        Cursor c = articleDB.rawQuery("SELECT * FROM articles", null);
        int contentIndex = c.getColumnIndex("content");
        int titleIndex = c.getColumnIndex("title");
        if(c.moveToFirst())
            titles.clear();
            content.clear();
            do
                titles.add(c.getString(titleIndex));
                content.add(c.getString(contentIndex));
            while (c.moveToNext());
            arrayAdapter.notifyDataSetChanged();
        
    
    public class DownloadTask extends AsyncTask<String, Void, String>
        @Override
        protected String doInBackground(String... strings) 
            String result = "";
            URL url;
            HttpsURLConnection urlConnection = null;
            try 
                url = new URL (strings[0]);
                urlConnection = (HttpsURLConnection) url.openConnection();
                InputStream in = urlConnection.getInputStream();
                InputStreamReader reader = new InputStreamReader(in);
                int data = reader.read();
                while (data != -1)
                    char current = (char) data;
                    result += current;
                    data = reader.read();
                
                //Log.i("URLContent",result);

                JSONArray jsonArray = new JSONArray(result);
                int numberOfItems = 20;
                if(jsonArray.length() <20)
                    numberOfItems = jsonArray.length();
                
                //to clear the table before add data
                articleDB.execSQL("DELETE FROM articles"); //will clear everything and add a new data
                for (int i=0;i<numberOfItems;i++ )
                    //Log.i("JSONItem",jsonArray.getString(i));
                    String articleId = jsonArray.getString(i);
                    url = new URL("https://hacker-news.firebaseio.com/v0/item/"+articleId+".json?print=pretty");
                    urlConnection = (HttpsURLConnection) url.openConnection();
                    in = urlConnection.getInputStream();
                    reader = new InputStreamReader(in);
                    data = reader.read();
                    String articleInfo = "";
                    while (data!= -1)
                        char current = (char) data;
                        articleInfo += current;
                        data = reader.read();
                    
                    //Log.i("ArticleInfo",articleInfo);
                    //separate title and URL
                    JSONObject jsonObject = new JSONObject(articleInfo);
                    if (!jsonObject.isNull("title") && !jsonObject.isNull("url"))
                        String articleTitle = jsonObject.getString("title");
                        String articleURL = jsonObject.getString("url");
                        //Log.i("info",articleTitle + articleURL);
                        url = new URL(articleURL);
                        urlConnection = (HttpsURLConnection) url.openConnection();
                        in = urlConnection.getInputStream();
                        reader = new InputStreamReader(in);
                        data = reader.read();
                        String articleContent = "";
                        while (data!= -1)
                            char current = (char) data;
                            articleContent += current;
                            data = reader.read();
                        
                        //Log.i("articleContent",articleContent);

                        String sql = "INSERT INTO articles(articleID,title,content) VALUES(? , ? , ?)";
                        SQLiteStatement statement = articleDB.compileStatement(sql);
                        statement.bindString(1,articleId);
                        statement.bindString(2,articleTitle);
                        statement.bindString(3,articleContent);
                        statement.execute();
                    
                
             catch (MalformedURLException e) 
                e.printStackTrace();
             catch (IOException e) 
                e.printStackTrace();
             catch (JSONException e) 
                e.printStackTrace();
            
            return null;
        
        @Override
        protected void onPostExecute(String s) 
            super.onPostExecute(s);
            //run when the download task is completed
            updateListView();
        
    

【问题讨论】:

尝试使用 Log 来测试连接,然后你的数据来确保它首先工作。 这里的逻辑是首先确保您收到正确的数据。第二确保数据与模型兼容并且您可以解析它。第三,它在列表中正确膨胀。所以记录所有这些步骤。但是有两个注意事项。制作两个字符串列表是不好的做法,最好制作一个对象 NEWS,例如其中包含字符串标题和字符串描述。其次是获取 JSON 的逻辑不好。改造后它可以短得多。如果您需要帮助重构,请告诉我 如果该课程学习了这种开发方式 - 将其扔进垃圾箱。尝试改造 + 回收器 + 常规型号 class= 更清洁/更快 @BorisRuzanov 感谢您的建议。我是新手,我会尝试。很抱歉我没有得到关于改造的信息:(也许我应该谷歌它。 【参考方案1】:

我不认为您的问题是基于 SQLite 的,而是问题与数据的检索有关。

问题可能是:-

    您没有相应的权限。因此,您需要检查您的清单是否具有权限以及您是否已请求运行时权限。见Request App Permissions

    以下测试通过使用 API 24 之前的设备(模拟器)绕过运行时权限。

    检索时未使用适当的连接类型,即为 HTTP url 切换到 HTTP 连接。请参阅下面的代码以获取修复(可能是更好的选择)。

测试 1

例如,修改您的代码(从 中注释掉代码)以跳过数据检索并添加数据插入以进行测试显示插入的数据。

例如:-

    protected String doInBackground(String... strings) 
        String result = "";
        URL url;
        HttpsURLConnection urlConnection = null;
        HttpURLConnection xurlConnection = null; //ADDED for stage 2 testing

        /* <<<<<<<<<<< COMMENT OUT DATA RETRIEVAL >>>>>>>>>>
        try 
            url = new URL (strings[0]);
            urlConnection = (HttpsURLConnection) url.openConnection();
            InputStream in = urlConnection.getInputStream();
            InputStreamReader reader = new InputStreamReader(in);
            int data = reader.read();
            while (data != -1)
                char current = (char) data;
                result += current;
                data = reader.read();
            
            //Log.i("URLContent",result);

            JSONArray jsonArray = new JSONArray(result);
            int numberOfItems = 20;
            if(jsonArray.length() <20)
                numberOfItems = jsonArray.length();
            
            //to clear the table before add data
            articleDB.execSQL("DELETE FROM articles"); //will clear everything and add a new data
            for (int i=0;i<numberOfItems;i++ )
                //Log.i("JSONItem",jsonArray.getString(i));
                String articleId = jsonArray.getString(i);
                url = new URL("https://hacker-news.firebaseio.com/v0/item/"+articleId+".json?print=pretty");
                urlConnection = (HttpsURLConnection) url.openConnection();
                in = urlConnection.getInputStream();
                reader = new InputStreamReader(in);
                data = reader.read();
                String articleInfo = "";
                while (data!= -1)
                    char current = (char) data;
                    articleInfo += current;
                    data = reader.read();
                
                //Log.i("ArticleInfo",articleInfo);
                //separate title and URL
                JSONObject jsonObject = new JSONObject(articleInfo);
                if (!jsonObject.isNull("title") && !jsonObject.isNull("url"))
                    String articleTitle = jsonObject.getString("title");
                    String articleURL = jsonObject.getString("url");
                    //Log.i("info",articleTitle + articleURL);
                    url = new URL(articleURL);
                    xurlConnection =  (HttpURLConnection) url.openConnection();
                    in = xurlConnection.getInputStream();
                    reader = new InputStreamReader(in);
                    data = reader.read();
                    String articleContent = "";
                    while (data!= -1)
                        char current = (char) data;
                        articleContent += current;
                        data = reader.read();
                    
                    //Log.i("articleContent",articleContent);

                    String sql = "INSERT INTO articles(articleID,title,content) VALUES(? , ? , ?)";
                    SQLiteStatement statement = articleDB.compileStatement(sql);
                    statement.bindString(1,articleId);
                    statement.bindString(2,articleTitle);
                    statement.bindString(3,articleContent);
                    statement.execute();
                
            
         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
         catch (JSONException e) 
            e.printStackTrace();
        
        <<<<<<<<<< END OF COMMENTED OUT CODE >>>>>>>>>> */
        ContentValues cv = new ContentValues();
        cv.put("articleID",1);
        cv.put("title","Title");
        cv.put("content","Some content");
        articleDB.insert("articles",null,cv);
        return null;
    

结果:-

这是预期的,即只显示标题

测试 2

删除注释掉的代码,最初会产生Caused by: java.lang.SecurityException: Permission denied (missing INTERNET permission?)

测试 3

使用 API 24 之前的设备(为了方便不必请求运行时权限)并将清单更改为包含 &lt;uses-permission android:name="android.permission.INTERNET"&gt;&lt;/uses-permission&gt;

结果

 Caused by: java.lang.ClassCastException: com.android.okhttp.internal.huc.HttpURLConnectionImpl cannot be cast to javax.net.ssl.HttpsURLConnection
    at aso.aso57271930listview.MainActivity$DownloadTask.doInBackground(MainActivity.java:117)
    at aso.aso57271930listview.MainActivity$DownloadTask.doInBackground(MainActivity.java:67)

第 117 行是 urlConnection = (HttpsURLConnection) url.openConnection();

测试 4

在第 117 行添加断点并在调试模式下运行会导致:-

网址不是https而是http

测试 5

按照以下方式添加行:-

protected String doInBackground(String... strings) 
        String result = "";
        URL url;
        HttpsURLConnection urlConnection = null;
        HttpURLConnection xurlConnection = null; //<<<<<<<<<< ADDED for stage 2 testing

然后更改为使用:-

                if (!jsonObject.isNull("title") && !jsonObject.isNull("url"))
                    String articleTitle = jsonObject.getString("title");
                    String articleURL = jsonObject.getString("url");
                    //Log.i("info",articleTitle + articleURL);
                    url = new URL(articleURL);
                    //urlConnection =  (HttpsURLConnection) url.openConnection(); //<<<<<<<<<< commented out
                    xurlConnection = (HttpURLConnection) url.openConnection(); //<<<<<<<<<< added to replace commented out line. 
                    in = urlConnection.getInputStream();
                    reader = new InputStreamReader(in);
                    data = reader.read();
                    String articleContent = "";
                    while (data!= -1)
                        char current = (char) data;
                        articleContent += current;
                        data = reader.read();
                    
                    //Log.i("articleContent",articleContent);

                    String sql = "INSERT INTO articles(articleID,title,content) VALUES(? , ? , ?)";
                    SQLiteStatement statement = articleDB.compileStatement(sql);
                    statement.bindString(1,articleId);
                    statement.bindString(2,articleTitle);
                    statement.bindString(3,articleContent);
                    statement.execute();
                

结果:-

【讨论】:

感谢您为提供详细答案所做的努力! 感谢您的解释。【参考方案2】:

您的表没有在数据库中创建,请更改

articleDB.execSQL("CREATE TABLE IF NOT EXISTS articles (id INTEGER PRIMARY KEY, articleID INTEGER,title VARCHAR,content VARCHAR)");

articleDB.execSQL("CREATE TABLE IF NOT EXISTS articles (id INTEGER PRIMARY KEY, articleID INTEGER,title TEXT,content TEXT)");

【讨论】:

谢谢,我按照建议进行了尝试,但输出相同,列表视图中没有标题。在运行控制台中,长时间显示为“正在启动应用程序”,没有任何其他输出,甚至没有错误。

以上是关于如何使用“标题”更新列表视图的主要内容,如果未能解决你的问题,请参考以下文章

如何使用从图库中选择的新图像更新列表视图 [重复]

如何使用来自另一个活动的自定义适配器更新列表视图?

如何在 AsyncTask 类方法中更新列表的文本视图?

如何使用 MVC 模型动态过滤 javafx 中的列表视图控件,同时以多种方式更新? [关闭]

如何将流生成器中的数据显示到文本字段中并更新来自列表视图?

如何更新列表视图中的记录以及android中的数据库