尝试使用 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);