2017-03-07 74 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) 

並確保你逝去的背景下您的適配器。