java - 内容解析器指向具有正确 URI 的错误表

标签 java android android-contentresolver

我在将查询调用到 PostCategoryContent Provider 的线路上遇到问题

我收到一条错误信息:

11-13 10:23:40.674: E/AndroidRuntime(26012): android.database.sqlite.SQLiteException: no such column: category_id (code 1): , while compiling: SELECT * FROM post WHERE (category_id=39)

即使 URI 指向另一个表 postCategory

任何人都可以指导我做错什么吗?

public class PostFragment extends SherlockListFragment implements LoaderCallbacks<Cursor> {


    private SimpleCursorAdapter adapter;

    private boolean dataRetrieved;

    private SlidingArea parent;

    PullToRefreshListView pullToRefreshView;

    EditText searchBox;

    Bundle args = new Bundle();

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        parent = (SlidingArea) getActivity();

        setHasOptionsMenu(true);    

        fillData(false);
    }

    @Override
    public void onResume() {
        super.onResume();

        parent.getSupportActionBar().setCustomView(R.layout.kpmg_actionbar_list_view);
        parent.getSupportActionBar().setDisplayShowCustomEnabled(true);
        parent.getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        final ImageView searchButton = (ImageView) parent.findViewById(R.id.kpmg_actionbar_image_search_list);

        searchButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if (searchBox.getVisibility() == View.GONE)
                {
                    searchBox.setVisibility(View.VISIBLE);
                    searchBox.requestFocus();
                    InputMethodManager imm = (InputMethodManager) parent.getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.showSoftInput(searchBox, InputMethodManager.SHOW_IMPLICIT);
                } else {
                    searchBox.setVisibility(View.GONE);
                    searchBox.clearFocus();
                    hideKeyboard(v);
                }
            }

        });     

        final ImageView refreshButton = (ImageView) parent.findViewById(R.id.kpmg_actionbar_image_refresh_list);

        refreshButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                getData(getString(R.string.kpmg_json_get_articles), true);
                refreshButton.setImageResource(R.drawable.kpmg_actionbar_refresh_dark);
                fillData(true);
            }

        }); 

        searchBox.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
                // When user changed the Text
                filterData(cs);
            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                    int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable s) {
                // TODO Auto-generated method stub

            }
        });

    }

    //Constant used as key for ID being passed in the bundle between fragments 
    public static final String NEWS_ID = "newsID";


    private void getData(String url, boolean showProgressDialog) {
        new Request(showProgressDialog).execute(new String[] {url});    
    }

    public class Request extends AsyncTask<String, Void, String> {

        ProgressDialog dialog;

        /* This is the only file that needs to be edited */

        private GetResponse response = null;

        private boolean showProgressDialog = true;

        public Request(boolean showProgressDialog)
        {
            super();
            this.showProgressDialog = showProgressDialog;
            response = new GetResponse();
        }   

        @Override
        protected void onPreExecute() {

            if (showProgressDialog) {
                dialog = new ProgressDialog(parent);
                dialog.setMessage("Retrieving latest information...");
                dialog.setIndeterminate(true);
                dialog.setCancelable(false);
                dialog.show();
            }
        }

        //This method must return the type specified in the constructor
        @Override
        protected String doInBackground(String... url) {
            response.setUrl(url[0]);

            String res = response.execute();

            // When it returns the "res" it will call onPostExecute
            return res;
        }

        @Override
        protected void onPostExecute(String result) {

            // Here we have response from server
            if ( isNetworkAvailable() ){

                try {

                    JSONObject json = new JSONObject(result);
                    JSONArray arr = json.getJSONArray("posts");

                    for (int i = arr.length() - 1; i >= 0; --i) {

                        JSONObject row = arr.getJSONObject(i);      

                        JSONArray arrCategories = row.getJSONArray("categories");
                        int Created = 0;
                        int Updated = 0;

                        for (int j = arrCategories.length() -1; j >= 0; --j){

                            JSONObject rowCategory = arrCategories.getJSONObject(j);

                            ContentValues categoryValues = new ContentValues();
                            categoryValues.put(PostCategoryTable.CATEGORY_ID, rowCategory.getInt("id"));

                            Cursor categoryCursor = parent.getContentResolver().query(PostCategoryContentProvider.CONTENT_URI, null, PostCategoryTable.CATEGORY_ID + "=" + categoryValues.getAsString(PostCategoryTable.CATEGORY_ID), null, null);

                            int categoryCount = categoryCursor.getCount();

                            if (categoryCount == 0) {

                                categoryValues.put(PostCategoryTable.ICON_NAME, rowCategory.getString("slug"));
                                categoryValues.put(PostCategoryTable.CATEGORY_NAME, rowCategory.getString("title"));
                                categoryValues.put(PostCategoryTable.PARENT_ID, rowCategory.getInt("parent"));
                                parent.getContentResolver().insert(PostCategoryContentProvider.CONTENT_URI, categoryValues);
                                Created++;
                            }

                            else {

                                categoryCursor.moveToFirst();

                                categoryValues.put(PostCategoryTable.ICON_NAME, rowCategory.getString("slug"));
                                categoryValues.put(PostCategoryTable.CATEGORY_NAME, rowCategory.getString("title"));
                                categoryValues.put(PostCategoryTable.PARENT_ID, rowCategory.getInt("parent"));

                                parent.getContentResolver().update(PostCategoryContentProvider.CONTENT_URI, categoryValues, PostCategoryTable.CATEGORY_ID + "=" + categoryValues.getAsString(PostCategoryTable.CATEGORY_ID), null);
                                Updated++;
                            }

                            categoryCursor.close();
                        }   

                        Toast.makeText(parent,"Created : " + "" + Created + " | Updated : " + "" + Updated, Toast.LENGTH_SHORT).show();

                        if (row.getString("status").equals("publish")) {

                            ContentValues values = new ContentValues();
                            values.put(PostTable.POST_ID, row.getString("id"));
                            values.put(PostTable.CONTENT, Html.fromHtml(row.getString(PostTable.CONTENT)).toString());
                            values.put(PostTable.EXCERPT, Html.fromHtml(row.getString(PostTable.EXCERPT)).toString());
                            //image
                            //imageurl
                            values.put(PostTable.DATE_MODIFIED, row.getString(PostTable.DATE_MODIFIED));
                            values.put(PostTable.DATE_PUBLISHED, row.getString(PostTable.DATE_PUBLISHED));
                            //thumbnail
                            //thumbnailurl
                            values.put(PostTable.TITLE, row.getString(PostTable.TITLE));
                            values.put(PostTable.URL, row.getString("online-url"));
                            values.put(PostTable.VIDEO_URL, row.getString("video-url"));

                            //Check for new Categories

                            //getThumbnail
//                              byte[] image = AppHelper.getBlobFromURL(row.getString(BlogTable.THUMBNAIL));
//                              if (image != null) {
//                                  
//                                  values.put(BlogTable.THUMBNAIL, image);
//                                  
//                              }

                            Cursor c = parent.getContentResolver().query(PostContentProvider.CONTENT_URI, null, PostTable.POST_ID + "=" + values.getAsString(PostTable.POST_ID), null, null);
                            int count = c.getCount();

                            if (count == 0) {

                                parent.getContentResolver().insert(PostContentProvider.CONTENT_URI, values);

                            }
                            else {

                                c.moveToFirst();
                                if (!(c.getString(c.getColumnIndex(PostTable.DATE_MODIFIED)).equalsIgnoreCase(values.getAsString(PostTable.DATE_MODIFIED)))) {
//                              
//                                      
//                                      if (c.getString(c.getColumnIndex(BlogTable.THUMBNAIL)) != values.get(BlogTable.THUMBNAIL)){
//                                          //reset image
//                                      }
//                                      
                                    parent.getContentResolver().update(PostContentProvider.CONTENT_URI, values, PostTable.POST_ID + "=" + values.getAsString(PostTable.POST_ID), null);

                                }
                            }
                            c.close();

                            //Here we should last retrieved time and used as part of the condition before retrieving data

                        }
                        else {

                            String currentID = row.getString("id");

                            // Delete unpublished fields
                            parent.getContentResolver().delete(PostContentProvider.CONTENT_URI, "_id = " + currentID, null);

                        }
                    }
                } catch (JSONException e) {

                    e.printStackTrace();

                }
            }
            else {

                Toast toast = Toast.makeText( parent , "You are not connected to the internet. Please check your connection, or try again later",
                        Toast.LENGTH_SHORT);
                toast.show();

            }           

            // Call onRefreshComplete when the list has been refreshed.
            pullToRefreshView.onRefreshComplete();
            super.onPostExecute(result);

            ImageView refreshButton = (ImageView) parent.findViewById(R.id.kpmg_actionbar_image_refresh_list);
            refreshButton.setImageResource(R.drawable.kpmg_actionbar_refresh);

            if (showProgressDialog) {
                dialog.dismiss();   
            }
        }

    }

    private void fillData(boolean isRefresh){

        //_id is expected from this method that is why we used it earlier
        String[] from = new String[] { PostTable.TITLE, PostTable.DATE_PUBLISHED, PostTable.EXCERPT};
        int[] to = new int[] { R.id.kpmg_text_news_title, R.id.kpmg_text_news_date, R.id.kpmg_text_news_excerpt};

        //initialize loader to call this class with a callback
        if (!isRefresh){
            getLoaderManager().initLoader(0, null, this);
        }
        else {
                if (searchBox.getText().length() == 0) {
                    getLoaderManager().restartLoader(0, null, this);
                }
                else {
                    getLoaderManager().restartLoader(0, args, this);
                }
        }

        //We create adapter to fill list with data, but we don't provide any data as it will be done by loader
        adapter = new SimpleCursorAdapter(parent, R.layout.kpmg_list_view, null, from, to, 0);

        adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
            @Override
            public boolean setViewValue(View view, Cursor cursor, int column) {

                if( column == cursor.getColumnIndex(PostTable.DATE_PUBLISHED) ){ // let's suppose that the column 0 is the date

                    TextView textDate = (TextView) view.findViewById(R.id.kpmg_text_news_date);
                    String dateStr = cursor.getString(cursor.getColumnIndex(PostTable.DATE_PUBLISHED));

                    String formattedDate = AppHelper.calculateRelativeDate(dateStr);
                    textDate.setText( "Posted - " + formattedDate);

                    return true;
                }
                return false;
            }
        });

        setListAdapter(adapter);

    }

    private void filterData(CharSequence cs){
        args.putString("Selection", cs.toString());
        getLoaderManager().restartLoader(0, args, this /*LoaderCallbacks<Cursor>*/);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle args) {

        String[] projection = new String[] { PostTable.TITLE, PostTable.DATE_PUBLISHED, PostTable.EXCERPT, PostTable.ID };

        CursorLoader loader;

        if (args == null) {
            Log.i("Arguments","None");
            loader = new CursorLoader(parent, PostContentProvider.CONTENT_URI, projection, null, null, PostTable.DATE_PUBLISHED + " DESC");
        }
        else {
            Log.i("Arguments","Full");
            String selectionKeyword = args.getString("Selection");
            String selection = PostTable.TITLE + " LIKE ? OR " + PostTable.CONTENT + " LIKE ? OR " + PostTable.EXCERPT + " LIKE ?";
            String[] selectionArgs = new String[] {"%" + selectionKeyword + "%","%" + selectionKeyword + "%","%" + selectionKeyword + "%"};
            loader = new CursorLoader(parent, PostContentProvider.CONTENT_URI, projection, selection, selectionArgs, PostTable.DATE_PUBLISHED + " DESC");
        }

        return loader;
    }


    public void onLoadFinished(Loader<Cursor> arg0, Cursor data) {
        adapter.swapCursor(data);

    }

    public void onLoaderReset(Loader<Cursor> arg0) {
        adapter.swapCursor(null);
    }
}

最佳答案

在哪一行抛出异常?该问题更可能是您的 SQLite 语法问题,而不是与 LoaderCursor 相关的任何问题。确保您的表已根据需要进行初始化。做一个DatabaseUtils.dumpCursor(cursor)来分析异常抛出之间Cursor的内容。另外,我会调查您对 LIKE 的使用...我看到有人对该关键字有疑问 before .

关于java - 内容解析器指向具有正确 URI 的错误表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13359368/

相关文章:

java - 使用java检测Windows注册表事件

java - 无法添加逻辑来对 Java/android 中现有比较器中的日期进行排序

android - 绿道安卓工作室

java - 绘制网格偏移

android-imageview - 如何从 Firebase 存储检索图像并显示它?获取 "No content provider"错误

java - spliterator 中的 action.accept(val) 的作用是什么

java - Mockito 中模拟方法的单元测试最佳实践

java - 如何为 Android 生成恒定的 UUId?

android - 如何在 API 29 以下从手机获取图像

android - 如何以编程方式从 Android 获取 whatsapp 联系人?