尝试使用Picasso库加载图像。无法获得背景

时间:2017-03-07 05:24:15

标签: android picasso android-context

在我的代码中,我使用ImageView项目填充RecyclerView,这些项目将保存从在线数据库中获取的一些照片。 我的应用程序将自动调用我的PosterViewHolder子类的bind()函数,以便在需要在布局上显示时,使用数据填充ImageView。

要从数据库中检索这些图像,我设置了一个名为ShowPoster的ASyncTask。 ShowPoster被设置为PosterViewHolder的子类,它允许我引用我想要填充的ImageView。

我的ASyncTask在一个单独的字符串上执行,允许我在不中断主UI线程的情况下使用网络功能(在Android中是必需的)。

从数据库中检索原始JSON并正确解析后,我有了imageURL,这是我将从数据库中提取的图像的URL。

然后我使用Picasso库从数据库中检索图像,并使用以下特定代码行将图像加载到名为posterView的ImageView中:

Picasso.with(this).load(imageURL).into(posterView);

这是我的错误发生的地方,特别是.with(this)的参数,我需要提供我的应用程序的上下文。

我已经尝试用函数调用替换this来获取应用程序上下文,比如Context.getApplicationContext(),但是在这个类中,似乎我无法调用这些函数。

我还尝试在我的主Activity中的onCreate()函数中实例化一个新的Context,然后将它传递给我的PosterAdapter类的构造函数,这样我就可以在我的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>

7 个答案:

答案 0 :(得分:4)

将Context声明为全局。然后在构造函数

中赋值
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中的上下文

 Picasso.with(context).load(imageURL).into(posterView);

答案 1 :(得分:0)

将您的上下文传递给此类,如

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())

等观看者

<强> FYI

  

this指的是当前的类。在你的情况下,你想通过   活动的背景

答案 2 :(得分:0)

从适配器存储上下文

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()

答案 3 :(得分:0)

Picasso API已更改

仅获取Picasso实例:

val picasso = Picasso.get()

不像以前那样将上下文作为参数传递

答案 4 :(得分:0)

在毕加索新版本中使用 get() 而不是 .with(context) 。 2.7+

 Picasso.get().load(imageURL).into(posterView);

答案 5 :(得分:-1)

声明Context全局并将上下文传递为Constructor参数。

public class PosterAdapter extends RecyclerView.Adapter<PosterAdapter.PosterViewHolder>{

private Context mContext;

public PosterAdapter(Context context, Other variables...){
        mContext = context;
    }
.
.
.

}

答案 6 :(得分:-2)

试试这个......

Picasso. With(getContext)  

确保将上下文传递给适配器。