当我加载我的应用程序时,它应该在2列10行gridview中显示20个电影海报。但由于某种原因,当我继续滚动它将继续加载相同的20张海报,所以几乎无限滚动。对Android开发还是新手,所以任何帮助都会很棒!
MovieAdapter
public class MovieAdapter extends CursorAdapter {
private final String LOG_TAG = MovieAdapter.class.getSimpleName();
public MovieAdapter(Context context, Cursor c, int flags){
super(context,c,flags);
}
private String convertCursorRowToUXFormat(Cursor cursor){
String poster = cursor.getString(MainActivityFragment.COL_MOVIE_URL);
return poster;
}
@Override
public View newView(Context context,Cursor cursor,ViewGroup parent){
View view = LayoutInflater.from(context).inflate(R.layout.poster_image, parent, false);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
final String POSTERIMAGE_BASE_URL = "http://image.tmdb.org/t/p/";
final String POSTERIMAGE_SIZE = "w500";
ImageView posterImage = (ImageView)view;
final String POSTERIMAGE_URL = POSTERIMAGE_BASE_URL + POSTERIMAGE_SIZE + convertCursorRowToUXFormat(cursor);
Picasso.with(context).load(POSTERIMAGE_URL).into(posterImage);
Log.v(LOG_TAG, "Poster Urls: " + POSTERIMAGE_URL);
}
}
MainActivityFragment
public class MainActivityFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>{
private static final int MOVIE_LOADER = 0;
private final String LOG_TAG = MainActivityFragment.class.getSimpleName();
private static final String[] MOVIE_COLUMNS = {
// MovieContract.MovieEntry.TABLE_NAME + "." +
MovieContract.MovieEntry._ID,
MovieContract.MovieEntry.COLUMN_MOVIE_POSTER
};
static final int COL_MOVIE_ID = 0;
static final int COL_MOVIE_URL = 1;
private MovieAdapter mMovieAdapter;
public MainActivityFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mMovieAdapter = new MovieAdapter(getActivity(),null,0);
final View rootView = inflater.inflate(R.layout.fragment_main, container, false);
GridView gridView = (GridView) rootView.findViewById(R.id.movieposter_image_gridview);
gridView.setAdapter(mMovieAdapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l){
Cursor cursor = (Cursor)adapterView.getItemAtPosition(position);
if(cursor != null) {
Intent intent = new Intent(getActivity(), DetailActivity.class)
.setData(MovieContract.MovieEntry.CONTENT_URI);
startActivity(intent);
Log.d("DEBUG", "Selected item position " + position + ", with id: " + l);
}
}
});
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
getLoaderManager().initLoader(MOVIE_LOADER, null, this);
super.onActivityCreated(savedInstanceState);
}
private void updateApplication() {
FetchMovieTask movieTask = new FetchMovieTask(getActivity());
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
String sortBy = prefs.getString(getString(R.string.pref_sort_by_key),
getString(R.string.pref_popular_default));
movieTask.execute(sortBy);
}
@Override
public void onStart() {
super.onStart();
updateApplication();
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle){
Uri movieUri = MovieContract.MovieEntry.CONTENT_URI;
return new CursorLoader(getActivity(),
movieUri,
MOVIE_COLUMNS,
null,
null,
null);
}
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor){
mMovieAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> cursorLoader){
mMovieAdapter.swapCursor(null);
}
}
FetchMovieTask
public class FetchMovieTask extends AsyncTask<String, Void, Void> {
private final String LOG_TAG = FetchMovieTask.class.getSimpleName();
private final Context mContext;
public FetchMovieTask(Context context) {
mContext = context;
}
private boolean DEBUG = true;
private void getMovieDataJSON(String movieJSONStr, int result)
throws JSONException {
final String MDB_RESULT = "results";
final String MDB_POSTER = "poster_path";
final String MDB_MOVIE_TITLE = "original_title";
final String MDB_MOVIE_PLOT = "overview";
final String MDB_MOVIE_RATING = "popularity";
final String MDB_RELEASE_DATE = "release_date";
try {
JSONObject movieJSON = new JSONObject(movieJSONStr);
JSONArray movieArray = movieJSON.getJSONArray(MDB_RESULT);
Vector<ContentValues> cVVector = new Vector<>(movieArray.length());
for (int i = 0; i < movieArray.length(); i++) {
String poster;
String title;
String plot;
String rating;
String releaseDate;
//Get theJSON object representing the movie
JSONObject movieDetail = movieArray.getJSONObject(i);
poster = movieDetail.getString(MDB_POSTER);
title = movieDetail.getString(MDB_MOVIE_TITLE);
plot = movieDetail.getString(MDB_MOVIE_PLOT);
rating = movieDetail.getString(MDB_MOVIE_RATING);
releaseDate = movieDetail.getString(MDB_RELEASE_DATE);
ContentValues movieDetailValues = new ContentValues();
movieDetailValues.put(MovieContract.MovieEntry.COLUMN_MOVIE_NAME, title);
movieDetailValues.put(MovieContract.MovieEntry.COLUMN_MOVIE_POSTER, poster);
movieDetailValues.put(MovieContract.MovieEntry.COLUMN_MOVIE_PLOT, plot);
movieDetailValues.put(MovieContract.MovieEntry.COLUMN_MOVIE_RATING, rating);
movieDetailValues.put(MovieContract.MovieEntry.COLUMN_MOVIE_REDATE, releaseDate);
cVVector.add(movieDetailValues);
}
int inserted = 0;
if (cVVector.size() > 0) {
ContentValues[] cvArray = new ContentValues[cVVector.size()];
cVVector.toArray(cvArray);
inserted = mContext.getContentResolver().bulkInsert(MovieContract.MovieEntry.CONTENT_URI, cvArray);
}
Log.d(LOG_TAG, "FetchMovieTask Complete. " + inserted + " Inserted");
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
}
@Override
protected Void doInBackground (String...params){
if (params.length == 0) {
return null;
}
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String movieJSONStr = null;
int result = 20;
try {
final String MOVIE_BASE_URL = "http://api.themoviedb.org/3/movie";
Uri builtUri = Uri.parse(MOVIE_BASE_URL).buildUpon()
.appendPath(params[0])
.appendQueryParameter("api_key", BuildConfig.MOVIE_API_KEY)
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG, "Built URI " + builtUri.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
return null;
}
movieJSONStr = buffer.toString();
getMovieDataJSON(movieJSONStr, result);
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
}
catch(JSONException e){
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return null;
}
}
MovieProvider
public class MovieProvider extends ContentProvider {
// The URI Matcher used by this content provider.
private static final UriMatcher sUriMatcher = buildUriMatcher();
private MovieDbHelper mOpenHelper;
static final int MOVIE = 100;
static UriMatcher buildUriMatcher(){
final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
final String authority = MovieContract.CONTENT_AUTHORITY;
matcher.addURI(authority,MovieContract.PATH_MOVIE, MOVIE);
return matcher;
}
@Override
public boolean onCreate(){
mOpenHelper = new MovieDbHelper(getContext());
return true;
}
@Override
public String getType(Uri uri){
final int match = sUriMatcher.match(uri);
switch (match){
case MOVIE:
return MovieContract.MovieEntry.CONTENT_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)){
case MOVIE: {
retCursor = mOpenHelper.getReadableDatabase().query(
MovieContract.MovieEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
null
);
break;
}
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
retCursor.setNotificationUri(getContext().getContentResolver(),uri);
return retCursor;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
Uri returnUri;
switch (match) {
case MOVIE: {
long _id = db.insert(MovieContract.MovieEntry.TABLE_NAME,null,values);
if(_id > 0)
// returnUri = MovieContract.MovieEntry.buildMovieUri(_id);
returnUri = MovieContract.MovieEntry.CONTENT_URI;
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);
db.close();
return returnUri;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
int rowsDeleted;
if (null == selection) selection = "1";
switch (match){
case MOVIE:
rowsDeleted = db.delete(MovieContract.MovieEntry.TABLE_NAME,selection,selectionArgs);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
if (rowsDeleted != 0) {
getContext().getContentResolver().notifyChange(uri,null);
}
return rowsDeleted;
}
@Override
public int update(
Uri uri, ContentValues values, String selection, String[] selectionArgs) {
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
int rowsUpdated;
switch (match){
case MOVIE:
rowsUpdated= db.update(MovieContract.MovieEntry.TABLE_NAME,values,selection,selectionArgs);
break;
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
if (rowsUpdated != 0) {
getContext().getContentResolver().notifyChange(uri,null);
}
return rowsUpdated;
}
@Override
public int bulkInsert(Uri uri,ContentValues[] values) {
final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
final int match = sUriMatcher.match(uri);
switch (match) {
case MOVIE:
db.beginTransaction();
int returnCount = 0;
try {
for (ContentValues value : values) {
long _id = db.insert(MovieContract.MovieEntry.TABLE_NAME,null,value);
if(_id != -1) {
returnCount++;
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
getContext().getContentResolver().notifyChange(uri,null);
return returnCount;
default:
return super.bulkInsert(uri,values);
}
}
@Override
@TargetApi(11)
public void shutdown() {
mOpenHelper.close();
super.shutdown();
}
}