尝试使用 Picasso 库加载图像。无法获取上下文
Trying to load an image using Picasso library. Cant get the context
在我的代码中,我使用 ImageView 项目填充 RecyclerView,这些项目将保存从在线数据库中拍摄的一些照片。
当需要在布局上显示时,我的应用程序将自动调用我的 PosterViewHolder subclass 的 bind()
函数以用数据填充 ImageView。
为了从数据库中检索这些图像,我设置了一个名为 ShowPoster
的 ASyncTask。 ShowPoster
设置为 PosterViewHolder 的子 class,这使我可以引用我要填充的 ImageView。
我的 ASyncTask 在单独的字符串上执行,允许我在不中断主 UI 线程的情况下使用网络功能(这在 Android 中是强制性的)。
从数据库中检索原始 JSON 并对其进行适当解析后,我得到了图像 URL,这是我将从数据库中提取的图像的 URL。
然后我使用 Picasso 库从数据库中检索图像,并将图像加载到我的名为 posterView
的 ImageView 中,使用以下特定代码行:
Picasso.with(this).load(imageURL).into(posterView);
这是我的错误发生的地方,特别是在 .with(this)
的参数中,我需要在其中提供我的应用程序的上下文。
我尝试用函数调用替换 this
来获取应用程序上下文,例如 Context.getApplicationContext(),但是在这个 class 中,我似乎无法调用这些函数。
我也试过在我的主 Activity 中的 onCreate()
函数中实例化一个新的上下文,然后将它传递给我的 PosterAdapter class 的构造函数,以便我可以参考它在我的 ASyncTask 中而不进行任何函数调用,它偷偷经过 IDE 并编译,但应用程序在 运行 时崩溃。
在寻求解决问题的过程中,我偶然发现有人提到 AndroidManifest 中没有 android:name=""
与问题有关,但我不完全确定除了包名称之外,在这个字段中放什么。
作为参考,这是我的代码和我的清单
代码:(完整重新发布,API 键被删减)
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();
}
}
}
清单:
<?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>
将上下文声明为全局。然后在构造函数中赋值
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();
}
那就用毕加索的语境
Picasso.with(context).load(imageURL).into(posterView);
将你的上下文传递给这个 class 赞
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;
}
}
}
并像 PosterViewHolder(view,getApplicationContext())
这样使用你的视图持有者
仅供参考
this
refers to the current class. In your case, you want to pass the
activity's context
声明上下文全局并将上下文作为构造函数参数传递。
public class PosterAdapter extends RecyclerView.Adapter<PosterAdapter.PosterViewHolder>{
private Context mContext;
public PosterAdapter(Context context, Other variables...){
mContext = context;
}
.
.
.
}
存储来自适配器的上下文
private Context mContext;
public PosterAdapter(Context context, int numItems, String query){
this.mContext = context;
在 ViewHolder 中使用 PosterAdapter.this.mContext
或者使用您的 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);
}
并且您可以在 ViewHolder
中使用 this.itemView.getContext()
试试这个.....
Picasso. With(getContext)
并确保将上下文传递给适配器。
毕加索 API 变了
获取 Picasso 实例只需:
val picasso = Picasso.get()
没有像以前那样将上下文作为参数传递
在 picasso 新版本中使用 get() 而不是 .with(context) 。对于 2.7+
Picasso.get().load(imageURL).into(posterView);
在我的代码中,我使用 ImageView 项目填充 RecyclerView,这些项目将保存从在线数据库中拍摄的一些照片。
当需要在布局上显示时,我的应用程序将自动调用我的 PosterViewHolder subclass 的 bind()
函数以用数据填充 ImageView。
为了从数据库中检索这些图像,我设置了一个名为 ShowPoster
的 ASyncTask。 ShowPoster
设置为 PosterViewHolder 的子 class,这使我可以引用我要填充的 ImageView。
我的 ASyncTask 在单独的字符串上执行,允许我在不中断主 UI 线程的情况下使用网络功能(这在 Android 中是强制性的)。
从数据库中检索原始 JSON 并对其进行适当解析后,我得到了图像 URL,这是我将从数据库中提取的图像的 URL。
然后我使用 Picasso 库从数据库中检索图像,并将图像加载到我的名为 posterView
的 ImageView 中,使用以下特定代码行:
Picasso.with(this).load(imageURL).into(posterView);
这是我的错误发生的地方,特别是在 .with(this)
的参数中,我需要在其中提供我的应用程序的上下文。
我尝试用函数调用替换 this
来获取应用程序上下文,例如 Context.getApplicationContext(),但是在这个 class 中,我似乎无法调用这些函数。
我也试过在我的主 Activity 中的 onCreate()
函数中实例化一个新的上下文,然后将它传递给我的 PosterAdapter class 的构造函数,以便我可以参考它在我的 ASyncTask 中而不进行任何函数调用,它偷偷经过 IDE 并编译,但应用程序在 运行 时崩溃。
在寻求解决问题的过程中,我偶然发现有人提到 AndroidManifest 中没有 android:name=""
与问题有关,但我不完全确定除了包名称之外,在这个字段中放什么。
作为参考,这是我的代码和我的清单
代码:(完整重新发布,API 键被删减)
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();
}
}
}
清单:
<?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>
将上下文声明为全局。然后在构造函数中赋值
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();
}
那就用毕加索的语境
Picasso.with(context).load(imageURL).into(posterView);
将你的上下文传递给这个 class 赞
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;
}
}
}
并像 PosterViewHolder(view,getApplicationContext())
仅供参考
this
refers to the current class. In your case, you want to pass the activity's context
声明上下文全局并将上下文作为构造函数参数传递。
public class PosterAdapter extends RecyclerView.Adapter<PosterAdapter.PosterViewHolder>{
private Context mContext;
public PosterAdapter(Context context, Other variables...){
mContext = context;
}
.
.
.
}
存储来自适配器的上下文
private Context mContext;
public PosterAdapter(Context context, int numItems, String query){
this.mContext = context;
在 ViewHolder 中使用 PosterAdapter.this.mContext
或者使用您的 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);
}
并且您可以在 ViewHolder
中使用this.itemView.getContext()
试试这个.....
Picasso. With(getContext)
并确保将上下文传递给适配器。
毕加索 API 变了
获取 Picasso 实例只需:
val picasso = Picasso.get()
没有像以前那样将上下文作为参数传递
在 picasso 新版本中使用 get() 而不是 .with(context) 。对于 2.7+
Picasso.get().load(imageURL).into(posterView);