SQLView中的存储图像未显示在Gridview

时间:2016-10-11 15:19:41

标签: android sqlite gridview android-contentprovider

昨天我问了this我在哪里通过内容提供商向sqlite提供静态数据的问题。现在我想更进一步。我从网络服务器(使用Volley)下载一些数据并将它们再次存储在SQLite中。接下来我想用CursorLoader读取它们。但是我只能在Gridview中显示图像的标题。所以让我从我的代码开始。

MainActivityFragment

public class MainActivityFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{
static public ArrayList<MyCity> cityList;

private static final String LOG_TAG = MainActivityFragment.class.getSimpleName();
private MyCityAdpapter myCityAdpapter;
private static final int CURSOR_LOADER_ID = 0;
private GridView mGridView;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

}

public MainActivityFragment() {
    // Required empty public constructor
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    Cursor c =
            getActivity().getContentResolver().query(MyCityContract.MyCityEntry.CONTENT_URI,
                    new String[]{MyCityContract.MyCityEntry._ID},
                    null,
                    null,
                    null);
    if (c.getCount() == 0){
        updateImagesList();
    }
    // initialize loader
    getLoaderManager().initLoader(CURSOR_LOADER_ID, null, this);
    super.onActivityCreated(savedInstanceState);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    // inflate fragment_main layout
    final View rootView = inflater.inflate(R.layout.fragment_main_activity, container, false);

    cityList = new ArrayList<>();

    // initialize our FlavorAdapter
    myCityAdpapter = new MyCityAdpapter(getActivity(), null, 0, CURSOR_LOADER_ID);
    // initialize mGridView to the GridView in fragment_main.xml
    mGridView = (GridView) rootView.findViewById(R.id.flavors_grid);
    // set mGridView adapter to our CursorAdapter
    mGridView.setAdapter(myCityAdpapter);

    return rootView;

}


@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args){
    return new CursorLoader(getActivity(),
            MyCityContract.MyCityEntry.CONTENT_URI,
            null,
            null,
            null,
            null);
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    myCityAdpapter.swapCursor(data);
}
public void updateImagesList() {


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

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

        @Override
        public void onResponse(JSONArray response) {
            cityList.clear();
            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++) {
                    //insert images information into the database
                    JSONObject post = response.getJSONObject(i);

                    MyCity item = new MyCity();
                    item.setName(post.getString("title"));
                    item.setImage(API.IMAGE_URL + post.getString("image"));

                    ContentValues imageValues = new ContentValues();

                    imageValues.put(MyCityContract.MyCityEntry._ID, post.getString("id"));
                    imageValues.put(MyCityContract.MyCityEntry.COLUMN_NAME, post.getString("title"));
                    imageValues.put(MyCityContract.MyCityEntry.COLUMN_ICON, post.getString("image"));

                    getActivity().getContentResolver().insert(MyCityContract.MyCityEntry.CONTENT_URI, imageValues);

                    cityList.add(item);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

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

}

@Override
public void onLoaderReset(Loader<Cursor> loader){
    myCityAdpapter.swapCursor(null);
}

}

MyCityAdapter

public class MyCityAdpapter extends CursorAdapter {
private static final String LOG_TAG = MyCityAdpapter.class.getSimpleName();
private Context mContext;
private static int sLoaderID;

public MyCityAdpapter(Context context, Cursor c, int flags,int loaderID) {
    super(context, c, flags);
    Log.d(LOG_TAG, "MyCityAdpapter");
    mContext = context;
    sLoaderID = loaderID;
}
public static class ViewHolder {
    public final ImageView imageView;
    public final TextView textView;

    public ViewHolder(View view){
        imageView = (ImageView) view.findViewById(R.id.flavor_image);
        textView = (TextView) view.findViewById(R.id.flavor_text);
    }
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    int layoutId = R.layout.flavor_item;

    Log.d(LOG_TAG, "In new View");

    View view = LayoutInflater.from(context).inflate(layoutId, parent, false);
    ViewHolder viewHolder = new ViewHolder(view);
    view.setTag(viewHolder);

    return view;
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    ViewHolder viewHolder = (ViewHolder) view.getTag();

    Log.d(LOG_TAG, "In bind View");

    int versionIndex = cursor.getColumnIndex(MyCityContract.MyCityEntry.COLUMN_NAME);
    final String versionName = cursor.getString(versionIndex);
    Log.i(LOG_TAG, "Text reference extracted: " + versionName);
    viewHolder.textView.setText(versionName);

    int imageIndex = cursor.getColumnIndex(MyCityContract.MyCityEntry.COLUMN_ICON);
    int image = cursor.getInt(imageIndex);
    Log.i(LOG_TAG, "Image reference extracted: " + image);

    viewHolder.imageView.setImageResource(image);
  }
}

请记住,这个类的logcat给了我

I/MyCityAdpapter: Text reference extracted: Ancient Theatre - Larissa
I/MyCityAdpapter: Image reference extracted: 0
I/MyCityAdpapter: Text reference extracted: Old trains
I/MyCityAdpapter: Image reference extracted: 0

等等。

MyCityContract

public class MyCityContract {

public static final String CONTENT_AUTHORITY = "theo.testing.customloaders.app";

public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

public static final class MyCityEntry implements BaseColumns{
    //table name
    public static final String TABLE_MY_CITY = "my_city";
    //columns
    public static final String _ID = "_id";
    public static final String COLUMN_NAME = "name";
    public static final String COLUMN_ICON = "icon";

    // create content uri
    public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon()
            .appendPath(TABLE_MY_CITY).build();
    // create cursor of base type directory for multiple entries
    public static final String CONTENT_DIR_TYPE =
            ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + CONTENT_AUTHORITY + "/" + TABLE_MY_CITY;
    // create cursor of base type item for single entry
    public static final String CONTENT_ITEM_TYPE =
            ContentResolver.CURSOR_ITEM_BASE_TYPE +"/" + CONTENT_AUTHORITY + "/" + TABLE_MY_CITY;

    // for building URIs on insertion
    public static Uri buildFlavorsUri(long id){
        return ContentUris.withAppendedId(CONTENT_URI, id);
    }

   }
}

我的 MyCityDbHelperClass 可能存在错误,我存储了所有数据。

public class MyCityDbHelper  extends SQLiteOpenHelper{
public static final String LOG_TAG = MyCityDbHelper.class.getSimpleName();
//name & version
public static final String DATABASE_NAME = "city.db";
public static final int DATABASE_VERSION = 7;
// Create the database
public MyCityDbHelper(Context context) {
    super(context, DATABASE_NAME,null,DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
    final String SQL_CREATE_MY_CITY_TABLE = "CREATE TABLE " +
            MyCityContract.MyCityEntry.TABLE_MY_CITY + "(" + MyCityContract.MyCityEntry._ID +
            " INTEGER PRIMARY KEY AUTOINCREMENT, " +
            MyCityContract.MyCityEntry.COLUMN_NAME + " TEXT NOT NULL, " +
            MyCityContract.MyCityEntry.COLUMN_ICON + " INTEGER NOT NULL);";


    sqLiteDatabase.execSQL(SQL_CREATE_MY_CITY_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
    Log.w(LOG_TAG, "Upgrading database from version " + oldVersion + " to " +
            newVersion + ". OLD DATA WILL BE DESTROYED");
    // Drop the table
    sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + MyCityContract.MyCityEntry.TABLE_MY_CITY);
    sqLiteDatabase.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" +
            MyCityContract.MyCityEntry.TABLE_MY_CITY + "'");

    // re-create database
    onCreate(sqLiteDatabase);
 }
}

最后我有我的提供者。

public class MyCityProvider extends ContentProvider {
private static final String LOG_TAG = MyCityProvider.class.getSimpleName();
private static final UriMatcher sUriMatcher = buildUriMatcher();
private MyCityDbHelper myCityDbHelper;

//Codes for UriMatcher
private static final int MY_CITY = 100;
private static final int MY_CITY_WITH_ID = 200;


private static UriMatcher buildUriMatcher(){
    // Build a UriMatcher by adding a specific code to return based on a match
    // It's common to use NO_MATCH as the code for this case.
    final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    final String authority = MyCityContract.CONTENT_AUTHORITY;

    //add code for each URI
    matcher.addURI(authority,MyCityContract.MyCityEntry.TABLE_MY_CITY,MY_CITY);
    matcher.addURI(authority,MyCityContract.MyCityEntry.TABLE_MY_CITY + "/#",MY_CITY_WITH_ID);

    return matcher;

}
@Override
public boolean onCreate() {
    myCityDbHelper = new MyCityDbHelper(getContext());

    return true;
}

@Override
public String getType(Uri uri) {
    final int match = sUriMatcher.match(uri);

    switch (match){
        case MY_CITY: {
            return MyCityContract.MyCityEntry.CONTENT_DIR_TYPE;
        }
        case MY_CITY_WITH_ID:{
            return MyCityContract.MyCityEntry.CONTENT_ITEM_TYPE;

        }
        default:{
            throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
    }
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder){
    Cursor retCursor;
    switch(sUriMatcher.match(uri)){
        // All Flavors selected
        case MY_CITY:{
            retCursor = myCityDbHelper.getReadableDatabase().query(
                    MyCityContract.MyCityEntry.TABLE_MY_CITY,
                    projection,
                    selection,
                    selectionArgs,
                    null,
                    null,
                    sortOrder);
            return retCursor;
        }
        // Individual flavor based on Id selected
        case MY_CITY_WITH_ID:{
            retCursor = myCityDbHelper.getReadableDatabase().query(
                    MyCityContract.MyCityEntry.TABLE_MY_CITY,
                    projection,
                    MyCityContract.MyCityEntry._ID + " = ?",
                    new String[] {String.valueOf(ContentUris.parseId(uri))},
                    null,
                    null,
                    sortOrder);
            return retCursor;
        }
        default:{
            // By default, we assume a bad URI
            throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
    }
}




@Override
public Uri insert(Uri uri, ContentValues contentValues) {
    final SQLiteDatabase db = myCityDbHelper.getWritableDatabase();

    Uri returnUri;

    switch (sUriMatcher.match(uri)){
        case MY_CITY:

            long _id = db.insertWithOnConflict(MyCityContract.MyCityEntry.TABLE_MY_CITY,null,contentValues,SQLiteDatabase.CONFLICT_REPLACE);
            Log.d("id",String.valueOf(_id));
            // insert unless it is already contained in the database
            if(_id>0){
                returnUri = MyCityContract.MyCityEntry.buildFlavorsUri(_id);
            }else {
                throw new android.database.SQLException("Failed to insert row into: " + uri);
            }
            break;
        default: {
            throw  new UnsupportedOperationException("Unknown uri: " + uri );
        }
    }

    getContext().getContentResolver().notifyChange(uri,null);
    return returnUri;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    final SQLiteDatabase db = myCityDbHelper.getWritableDatabase();
    final int match = sUriMatcher.match(uri);
    int numDeleted;
    switch(match){
        case MY_CITY:
            numDeleted = db.delete(
                    MyCityContract.MyCityEntry.TABLE_MY_CITY, selection, selectionArgs);
            // reset _ID
            db.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" +
                    MyCityContract.MyCityEntry.TABLE_MY_CITY + "'");
            break;
        case MY_CITY_WITH_ID:
            numDeleted = db.delete(MyCityContract.MyCityEntry.TABLE_MY_CITY,
                    MyCityContract.MyCityEntry._ID + " = ?",
                    new String[]{String.valueOf(ContentUris.parseId(uri))});
            // reset _ID
            db.execSQL("DELETE FROM SQLITE_SEQUENCE WHERE NAME = '" +
                    MyCityContract.MyCityEntry.TABLE_MY_CITY  + "'");

            break;
        default:
            throw new UnsupportedOperationException("Unknown uri: " + uri);
    }

    return numDeleted;
}


@Override
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs){
    final SQLiteDatabase db = myCityDbHelper.getWritableDatabase();
    int numUpdated = 0;

    if (contentValues == null){
        throw new IllegalArgumentException("Cannot have null content values");
    }

    switch(sUriMatcher.match(uri)){
        case MY_CITY:{
            numUpdated = db.update(MyCityContract.MyCityEntry.TABLE_MY_CITY,
                    contentValues,
                    selection,
                    selectionArgs);
            break;
        }
        case MY_CITY_WITH_ID: {
            numUpdated = db.update(MyCityContract.MyCityEntry.TABLE_MY_CITY,
                    contentValues,
                    MyCityContract.MyCityEntry._ID + " = ?",
                    new String[] {String.valueOf(ContentUris.parseId(uri))});
            break;
        }
        default:{
            throw new UnsupportedOperationException("Unknown uri: " + uri);
        }
    }

    if (numUpdated > 0){
        getContext().getContentResolver().notifyChange(uri, null);
    }

    return numUpdated;
   }
}

为什么图像不在那里?我一直想解决存储动态数据的问题,并在离线模式下读取它们:)。

谢谢,

西奥。

1 个答案:

答案 0 :(得分:1)

您正在将数据库存储在数据库中,但是您正在MyCityAdapter中读取整数。您需要在bindView()方法中再次获取图片网址。获得图像的网址后,您将不得不下载并存储图像。但是没有必要自己写出来。我推荐Picasso库。将此库添加到您的dependecies后,您可以将图像设置为imageView,如下所示:Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

所以,你的bindView()方法体将是这样的:

@Override
public void bindView(View view, Context context, Cursor cursor) {
   ViewHolder viewHolder = (ViewHolder) view.getTag();

   Log.d(LOG_TAG, "In bind View");

   int versionIndex = cursor.getColumnIndex(MyCityContract.MyCityEntry.COLUMN_NAME);
   final String versionName = cursor.getString(versionIndex);
   Log.i(LOG_TAG, "Text reference extracted: " + versionName);
   viewHolder.textView.setText(versionName);

   int imageIndex = cursor.getColumnIndex(MyCityContract.MyCityEntry.COLUMN_ICON);
   String imageUrl = cursor.getString(imageIndex);
   Log.i(LOG_TAG, "Image reference extracted: " + image);

   Picasso.with(context).load(imageUrl).into(viewHolder.imageView);
}