2017-03-07 79 views
1

在我的代码中,我用ImageView项目填充RecyclerView项目,该项目将保存从在线数据库中获取的一些照片。
当我们的应用程序需要在布局上显示时,我的应用程序将自动调用PosterViewHolder子类的bind()函数以使用数据填充ImageView。尝试使用毕加索图书馆加载图像。无法获取上下文

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

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

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

然后我用毕加索库从数据库中检索图像,并将图像加载到我的ImageView,命名为posterView,使用这段代码的具体行:

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

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

我试着用this代替函数调用来获取应用程序上下文,比如Context.getApplicationContext(),但是在这个类中看起来我无法调用这些函数。

我也试图在我的主要活动在我onCreate()函数实例化一个新的环境,然后将它传递给我的PosterAdapter类的构造函数,这样我可以在我的AsyncTask内引用它不做任何函数调用,它偷偷过去IDE并编译,但运行时应用程序崩溃。

在我寻求解决我的问题的过程中,我偶然发现有人提到在AndroidManifest中没有android:name=""与该问题有关,但我不完全确定要将该字段放在软件包名称之外。

仅供参考,这里是我的代码,我的清单

CODE:(转贴全面,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> 
+0

你可以发布你的完整的适配器代码? – Ash

+0

从托管活动传递上下文并在Picasso.with中使用它() –

+1

您可以从posterView获取上下文。 'posterView.getContext()'。检查空值是个好主意。 –

回答

3

申报语境全球。然后在构造函数赋值

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); 
+1

您应该理想地将上下文存储在适配器中,而不是在每个ViewHolder中 –

+1

谢谢!如果我可以更进一步,为什么使用ItemView.getContext()?我的理解是,上下文充满了关于应用程序的信息,而不是特定的项目。是itemView从超级调用getContext,或者是我的理解不正确? –

+0

为清楚理解参考https://guides.codepath.com/android/Using-Context – sasikumar

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指当前类。在你的情况,你想通过 活动的背景下

-1

申报语境全球,并通过上下文构造方法的参数。

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

private Context mContext; 

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

} 
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()
+0

@ M.Ashish没有什么是错的。请不要编辑 –

+0

Dude在(this.mContext)中不需要this,因为context与mContext不同。但是,这在PosterViewHolder()构造函数中是完全正确的。 –

+0

我知道没有必要。但那是你的意见。尽管冗长,我仍然喜欢这样做 –

-2

试试这个.....

Picasso. With(getContext) 

并确保你逝去的背景下您的适配器。