Reputation: 2124
In my code, I am populating a RecyclerView with ImageView items that will hold some pictures taken from an online database.
My application will call the bind()
function of my PosterViewHolder subclass automatically to populate the ImageViews with data, when they need to be displayed on the layout.
To retrieve these images from the database, I setup an ASyncTask, named ShowPoster
. ShowPoster
is set up as a subclass of PosterViewHolder, which allows me to reference the ImageView which I am trying to populate.
My ASyncTask executes on a separate string, allowing me to use network functions without interrupting the main UI thread (which is mandatory in Android).
After retrieving the raw JSON from the database, and parsing it appropriately, I have imageURL, which is the URL of the image I will pull from the database.
I then use the Picasso library to retrieve the image from the database, and load the image into my ImageView, named posterView
, using this specific line of code:
Picasso.with(this).load(imageURL).into(posterView);
This is where my error occurs, specifically in the parameters of .with(this)
, where I need to provide the context of my app.
I have tried substituting this
with function calls to get application context, like Context.getApplicationContext(), but in this class, it appears I cannot call these functions.
I have also tried instantiating a new Context in my onCreate()
function in my main Activity, then passing it to the constructor of my PosterAdapter class, so that I can reference it within my ASyncTask without making any function calls, which sneaks past the IDE and compiles, but the application crashes when run.
In my quest to find a solution to my problem, I stumbled across someone mentioning that not having android:name=""
in the AndroidManifest is related to the problem, but I'm not entirely sure what to put in this field beyond the package name.
For reference, here is my code, and my manifest
CODE: (Reposted in full, API Keys censored)
package com.example.android.myapplication;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;
public class PosterAdapter extends RecyclerView.Adapter<PosterAdapter.PosterViewHolder>{
private String POPULAR_MOVIES_URL = "https://api.themoviedb.org/3/movie/popular?api_key=XXXX";
private String RATED_MOVIES_URL = "https://api.themoviedb.org/3/movie/top_rated?api_key=XXXX";
private String searchQueryURL;
private int mNumberItems;
private MovieDBJSONTools mJSONTools;
public PosterAdapter(int numItems, String query){
mNumberItems = numItems;
mJSONTools = new MovieDBJSONTools();
searchQueryURL = null;
switch(query){
case "popular":
searchQueryURL = POPULAR_MOVIES_URL;
break;
case "rating":
searchQueryURL = RATED_MOVIES_URL;
break;
}
}
@Override
public PosterViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType){
Context context = viewGroup.getContext();
int layoutIdForListItem = R.layout.poster_item;
LayoutInflater inflater = LayoutInflater.from(context);
boolean shouldAttachToParentImmediately = false;
View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
PosterViewHolder viewHolder = new PosterViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(PosterViewHolder viewHolder, int position){
viewHolder.bind(position);
}
@Override
public int getItemCount(){
return mNumberItems;
}
class PosterViewHolder extends RecyclerView.ViewHolder{
ImageView posterView;
public PosterViewHolder(View itemView) {
super(itemView);
posterView = (ImageView) itemView.findViewById(R.id.poster_item);
}
void bind(int pos){
new ShowPoster().execute(pos);
}
private class ShowPoster extends AsyncTask<Integer, Void, Void>{
@Override
protected Void doInBackground(Integer... params) {
try {
String rawJSON = getResponseFromHttpURL(new URL(searchQueryURL));
String imageURL = mJSONTools.GetMoviePosterURL(rawJSON, params[0]);
Picasso.with(this).load(imageURL).into(posterView);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
private String getResponseFromHttpURL(URL url) throws IOException {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = urlConnection.getInputStream();
Scanner scanner = new Scanner(in);
scanner.useDelimiter("\\A");
boolean hasInput = scanner.hasNext();
if (hasInput) {
String next = scanner.next();
return next;
} else {
return null;
}
} finally {
urlConnection.disconnect();
}
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.myapplication">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="Popular Movies"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Upvotes: 1
Views: 3592
Reputation: 1
use the get() instead of .with(context) in picasso new version. for 2.7+
Picasso.get().load(imageURL).into(posterView);
Upvotes: 0
Reputation: 37969
Picasso API has changed
To get Picasso instance just:
val picasso = Picasso.get()
Without passing the context as param as before
Upvotes: 0
Reputation: 1
try this.....
Picasso. With(getContext)
And make sure you are passing context to your adapter.
Upvotes: -2
Reputation: 191728
Store the Context from the Adapter
private Context mContext;
public PosterAdapter(Context context, int numItems, String query){
this.mContext = context;
Use in the ViewHolder as PosterAdapter.this.mContext
Or use your itemView
class PosterViewHolder extends RecyclerView.ViewHolder{
final View itemView;
ImageView posterView;
public PosterViewHolder(View itemView) {
super(itemView);
this.itemView = itemView;
posterView = (ImageView) itemView.findViewById(R.id.poster_item);
}
And you can use this.itemView.getContext()
within the ViewHolder
Upvotes: 0
Reputation: 823
Declare Context global and pass context as Constructor parameter.
public class PosterAdapter extends RecyclerView.Adapter<PosterAdapter.PosterViewHolder>{
private Context mContext;
public PosterAdapter(Context context, Other variables...){
mContext = context;
}
.
.
.
}
Upvotes: -1
Reputation: 13348
Declare Context as global . Then assign value in the constructor
private class PosterViewHolder extends RecyclerView.ViewHolder{
ImageView posterView;
Context context;
public PosterViewHolder(View itemView) {
super(itemView);
posterView = (ImageView) itemView.findViewById(R.id.poster_item);
context = itemView.getContext();
}
then use the context in picasso
Picasso.with(context).load(imageURL).into(posterView);
Upvotes: 4
Reputation: 6813
Pass your context to this class like
private class PosterViewHolder extends RecyclerView.ViewHolder{
ImageView posterView;
Context context;
public PosterViewHolder(View itemView,Context context) {
super(itemView);
this.context=context;
posterView = (ImageView) itemView.findViewById(R.id.poster_item);
}
void bind(int pos){
new ShowPoster().execute(pos);
}
private class ShowPoster extends AsyncTask<Integer, Void, Void>{
private Bitmap poster;
@Override
protected Void doInBackground(Integer... params) {
poster = null;
try {
String rawJSON = getResponseFromHttpURL(new URL(searchQueryURL));
String imageURL = mJSONTools.GetMoviePosterURL(rawJSON, params[0]);
Picasso.with(context).load(imageURL).into(posterView);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
And use your view holder like PosterViewHolder(view,getApplicationContext())
FYI
this
refers to the current class. In your case, you want to pass the activity's context
Upvotes: 0