2017-05-29 11 views
0

私はJSON Urlを解析するためにRecyclerViewとRetrofitを使用してデータをフェッチするアンドロイドアプリケーションに取り組んでいます。私はこれに関するチュートリアルに従っていたGithubNativeExpressAdView java.lang.IndexOutOfBoundsException:無効なインデックス0、サイズが0

Android Studioの私のプロジェクトはエラーがなく、私はアプリケーションを実行することができます。しかし、私がMainActivityを開くとクラッシュします。私は、これは次の行である

java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0 

を取得しています

エラーがsetUpAndLoadNativeExpressAds

final NativeExpressAdView adView = (NativeExpressAdView) mRecyclerViewItems.get(i); 

これはMainActivity

である上にある
public class MainActivity extends AppCompatActivity{ 

    public static final int ITEMS_PER_AD = 3; 
    private static final int NATIVE_EXPRESS_AD_HEIGHT = 150; 
    private static final String AD_UNIT_ID = ADMOB_NATIVE_MENU_ID; 

    private StartAppAd startAppAd = new StartAppAd(this); 
    private RecyclerView mRecyclerView; 
    private List<Object> mRecyclerViewItems = new ArrayList<>(); 
    private KontenAdapter kontenAdapter; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 


     mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); 

     // Use this setting to improve performance if you know that changes 
     // in content do not change the layout size of the RecyclerView. 
     mRecyclerView.setHasFixedSize(true); 

     // Specify a linear layout manager. 
     RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); 
     mRecyclerView.setLayoutManager(layoutManager); 

//  mRecyclerViewItems = new ArrayList<>(); 

     // Update the RecyclerView item's list with menu items and Native Express ads. 
//  addMenuItemsFromJson(); 
     loadJSON(); 
//  initData(); 
     setUpAndLoadNativeExpressAds(); 

    } 



    /** 
    * Adds Native Express ads to the items list. 
    */ 
    private void addNativeExpressAds() { 

     // Loop through the items array and place a new Native Express ad in every ith position in 
     // the items List. 
     for (int i = 0; i <= mRecyclerViewItems.size(); i += ITEMS_PER_AD) { 
      final NativeExpressAdView adView = new NativeExpressAdView(MainActivity.this); 
      mRecyclerViewItems.add(i, adView); 
     } 
    } 

    /** 
    * Sets up and loads the Native Express ads. 
    */ 
    private void setUpAndLoadNativeExpressAds() { 
     mRecyclerView.post(new Runnable() { 
      @Override 
      public void run() { 
       final float scale = MainActivity.this.getResources().getDisplayMetrics().density; 
       // Set the ad size and ad unit ID for each Native Express ad in the items list. 
       for (int i = 0; i <= mRecyclerViewItems.size(); i += ITEMS_PER_AD) { 
        final NativeExpressAdView adView = (NativeExpressAdView) mRecyclerViewItems.get(i); 
        final CardView cardView = (CardView) findViewById(R.id.ad_card_view); 
        final int adWidth = cardView.getWidth() - cardView.getPaddingLeft() 
          - cardView.getPaddingRight(); 
        AdSize adSize = new AdSize((int) (adWidth/scale), NATIVE_EXPRESS_AD_HEIGHT); 
        adView.setAdSize(adSize); 
        adView.setAdUnitId(AD_UNIT_ID); 
       } 

       // Load the first Native Express ad in the items list. 
       loadNativeExpressAd(0); 
      } 
     }); 
    } 

    /** 
    * Loads the Native Express ads in the items list. 
    */ 
    private void loadNativeExpressAd(final int index) { 

     if (index >= mRecyclerViewItems.size()) { 
      return; 
     } 

     Object item = mRecyclerViewItems.get(index); 
     if (!(item instanceof NativeExpressAdView)) { 
      throw new ClassCastException("Expected item at index " + index + " to be a Native" 
        + " Express ad."); 
     } 

     final NativeExpressAdView adView = (NativeExpressAdView) item; 

     // Set an AdListener on the NativeExpressAdView to wait for the previous Native Express ad 
     // to finish loading before loading the next ad in the items list. 
     adView.setAdListener(new AdListener() { 
      @Override 
      public void onAdLoaded() { 
       super.onAdLoaded(); 
       // The previous Native Express ad loaded successfully, call this method again to 
       // load the next ad in the items list. 
       loadNativeExpressAd(index + ITEMS_PER_AD); 
      } 

      @Override 
      public void onAdFailedToLoad(int errorCode) { 
       // The previous Native Express ad failed to load. Call this method again to load 
       // the next ad in the items list. 
       Log.e("MainActivity", "The previous Native Express ad failed to load. Attempting to" 
         + " load the next Native Express ad in the items list."); 
       loadNativeExpressAd(index + ITEMS_PER_AD); 
      } 
     }); 

     // Load the Native Express ad. 
     adView.loadAd(new AdRequest.Builder().build()); 
    } 


    private void loadJSON() { 
     Retrofit retrofit = new Retrofit.Builder() 
       .baseUrl("https://api.myjson.com/") //https://api.myjson.com/bins/v4dzd 
       .addConverterFactory(GsonConverterFactory.create()) 
       .build(); 
     RequestInterface request = retrofit.create(RequestInterface.class); 
     Call<JSONResponse> call = request.getJSON(); 
     call.enqueue(new Callback<JSONResponse>() { 
      @Override 
      public void onResponse(Call<JSONResponse> call, Response<JSONResponse> response) { 
       JSONResponse jsonResponse = response.body(); 

       mRecyclerViewItems = new ArrayList<Object>(Arrays.asList(jsonResponse.getKonten())); 
       addNativeExpressAds(); 

       RecyclerView.Adapter adapter = new KontenAdapter(mRecyclerViewItems, getApplicationContext()); 
       mRecyclerView.setAdapter(adapter); 
      } 

      @Override 
      public void onFailure(Call<JSONResponse> call, Throwable t) { 
       Log.d("Error", t.getMessage()); 
      } 
     }); 

    } 

    /** 
    * Adds {@link KontenItem}'s from a JSON file. 
    */ 
    private void addMenuItemsFromJson() { 
     try { 
      String jsonDataString = readJsonDataFromFile(); 
      JSONArray menuItemsJsonArray = new JSONArray(jsonDataString); 

      for (int i = 0; i < menuItemsJsonArray.length(); ++i) { 

       JSONObject menuItemObject = menuItemsJsonArray.getJSONObject(i); 

       String menuItemName = menuItemObject.getString("name"); 
       String menuItemDescription = menuItemObject.getString("description"); 
       String menuItemPrice = menuItemObject.getString("price"); 
       String menuItemCategory = menuItemObject.getString("category"); 
       String menuItemImageName = menuItemObject.getString("photo"); 
       String menuItemUrl = menuItemObject.getString("url"); 

       KontenItem kontenItem = new KontenItem(menuItemName, menuItemDescription, menuItemPrice, 
         menuItemCategory, menuItemImageName, menuItemUrl); 
       mRecyclerViewItems.add(kontenItem); 
      } 
     } catch (IOException | JSONException exception) { 
      Log.e(MainActivity.class.getName(), "Unable to parse JSON file.", exception); 
     } 
    } 

    /** 
    * Reads the JSON file and converts the JSON data to a {@link String}. 
    * 
    * @return A {@link String} representation of the JSON data. 
    * @throws IOException if unable to read the JSON file. 
    */ 
    private String readJsonDataFromFile() throws IOException { 

     InputStream inputStream = null; 
     StringBuilder builder = new StringBuilder(); 

     try { 
      String jsonDataString = null; 
      inputStream = getResources().openRawResource(R.raw.menu_items_json); 
      BufferedReader bufferedReader = new BufferedReader(
        new InputStreamReader(inputStream, "UTF-8")); 
      while ((jsonDataString = bufferedReader.readLine()) != null) { 
       builder.append(jsonDataString); 
      } 
     } finally { 
      if (inputStream != null) { 
       inputStream.close(); 
      } 
     } 

     return new String(builder); 
    } 



} 

これはMyAdapterある

public class KontenAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { 
    // A menu item view type. 
    private static final int MENU_ITEM_VIEW_TYPE = 0; 

    // The Native Express ad view type. 
    private static final int NATIVE_EXPRESS_AD_VIEW_TYPE = 1; 

    // An Activity's Context. 
    private final Context mContext; 

    // The list of Native Express ads and menu items. 
    private final List<Object> mRecyclerViewItems; 


    public KontenAdapter(List<Object> recyclerViewItems, Context context) { 
     this.mContext = context; 
     this.mRecyclerViewItems = recyclerViewItems; 
    } 

    /** 
    * The {@link MenuItemViewHolder} class. 
    * Provides a reference to each view in the menu item view. 
    */ 
    public class MenuItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ 
     private TextView menuItemName; 
     private TextView menuItemDescription; 
     private TextView menuItemPrice; 
     private TextView menuItemCategory; 
     private ImageView menuItemImage; 
     private TextView menuItemUrl; 

     MenuItemViewHolder(View view) { 
      super(view); 
      menuItemImage = (ImageView) view.findViewById(R.id.menu_item_image); 
      menuItemName = (TextView) view.findViewById(R.id.menu_item_name); 
      menuItemPrice = (TextView) view.findViewById(R.id.menu_item_price); 
      menuItemCategory = (TextView) view.findViewById(R.id.menu_item_category); 
      menuItemDescription = (TextView) view.findViewById(R.id.menu_item_description); 
      menuItemUrl = (TextView) view.findViewById(R.id.menu_item_url); 

      view.setOnClickListener(this); 
     } 

     @Override 
     public void onClick(View v) { 

      Intent detailIntent = new Intent(v.getContext(), PostActivity.class); 
      detailIntent.putExtra("name",menuItemName.getText().toString()); 
      detailIntent.putExtra("url", menuItemUrl.getText().toString()); 

      mContext.startActivity(detailIntent); 

     } 
    } 

    /** 
    * The {@link NativeExpressAdViewHolder} class. 
    */ 
    public class NativeExpressAdViewHolder extends RecyclerView.ViewHolder { 

     NativeExpressAdViewHolder(View view) { 
      super(view); 
     } 
    } 

    @Override 
    public int getItemCount() { 
     return mRecyclerViewItems.size(); 
    } 

    /** 
    * Determines the view type for the given position. 
    */ 
    @Override 
    public int getItemViewType(int position) { 
     return (position % MainActivity.ITEMS_PER_AD == 0) ? NATIVE_EXPRESS_AD_VIEW_TYPE 
       : MENU_ITEM_VIEW_TYPE; 
    } 

    /** 
    * Creates a new view for a menu item view or a Native Express ad view 
    * based on the viewType. This method is invoked by the layout manager. 
    */ 
    @Override 
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { 
     switch (viewType) { 
      case MENU_ITEM_VIEW_TYPE: 
       View menuItemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(
         R.layout.menu_item_container, viewGroup, false); 
       return new MenuItemViewHolder(menuItemLayoutView); 
      case NATIVE_EXPRESS_AD_VIEW_TYPE: 
       // fall through 
      default: 
       View nativeExpressLayoutView = LayoutInflater.from(
         viewGroup.getContext()).inflate(R.layout.native_express_ad_container, 
         viewGroup, false); 
       return new NativeExpressAdViewHolder(nativeExpressLayoutView); 
     } 

    } 

    /** 
    * Replaces the content in the views that make up the menu item view and the 
    * Native Express ad view. This method is invoked by the layout manager. 
    */ 
    @Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
     int viewType = getItemViewType(position); 
     switch (viewType) { 
      case MENU_ITEM_VIEW_TYPE: 
       MenuItemViewHolder menuItemHolder = (MenuItemViewHolder) holder; 
       KontenItem kontenItem = (KontenItem) mRecyclerViewItems.get(position); 

       // Get the menu item image resource ID. 
       String imageName = kontenItem.getImageName(); 
       int imageResID = mContext.getResources().getIdentifier(imageName, "drawable", 
         mContext.getPackageName()); 

       // Add the menu item details to the menu item view. 
       menuItemHolder.menuItemImage.setImageResource(imageResID); 
       menuItemHolder.menuItemName.setText(kontenItem.getName()); 
       menuItemHolder.menuItemPrice.setText(kontenItem.getPrice()); 
       menuItemHolder.menuItemCategory.setText(kontenItem.getCategory()); 
       menuItemHolder.menuItemDescription.setText(kontenItem.getDescription()); 
       menuItemHolder.menuItemUrl.setText(kontenItem.getInstructionUrl()); 
       break; 
      case NATIVE_EXPRESS_AD_VIEW_TYPE: 
       // fall through 
      default: 
       NativeExpressAdViewHolder nativeExpressHolder = 
         (NativeExpressAdViewHolder) holder; 
       NativeExpressAdView adView = 
         (NativeExpressAdView) mRecyclerViewItems.get(position); 
       ViewGroup adCardView = (ViewGroup) nativeExpressHolder.itemView; 
       // The NativeExpressAdViewHolder recycled by the RecyclerView may be a different 
       // instance than the one used previously for this position. Clear the 
       // NativeExpressAdViewHolder of any subviews in case it has a different 
       // AdView associated with it, and make sure the AdView for this position doesn't 
       // already have a parent of a different recycled NativeExpressAdViewHolder. 
       if (adCardView.getChildCount() > 0) { 
        adCardView.removeAllViews(); 
       } 
       if (adView.getParent() != null) { 
        ((ViewGroup) adView.getParent()).removeView(adView); 
       } 

       // Add the Native Express ad to the native express ad view. 
       adCardView.addView(adView); 
     } 
    } 

} 

KontenItem.java

事前に
class KontenItem { 

    private final String name; 
    private final String description; 
    private final String price; 
    private final String category; 
    private final String imageName; 
    private final String instructionUrl; 

    public KontenItem(String name, String description, String price, String category, 
         String imageName, String instructionUrl) { 
     this.name = name; 
     this.description = description; 
     this.price = price; 
     this.category = category; 
     this.imageName = imageName; 
     this.instructionUrl = instructionUrl; 
    } 

    public String getName() { 
     return name; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public String getPrice() { 
     return price; 
    } 

    public String getCategory() { 
     return category; 
    } 

    public String getImageName() { 
     return imageName; 
    } 

    public String getInstructionUrl() { 
     return instructionUrl; 
    } 
} 

ありがとう!

答えて

0

あなたは、異なるスレッドでaddNativeExpressAds() for (int i = 0; i <= mRecyclerViewItems.size(); i += ITEMS_PER_AD) { final NativeExpressAdView adView = (NativeExpressAdView) mRecyclerViewItems.get(i);

を呼んでいます。したがって、初期化の前にmRecyclerViewItems.get(i)が使用されます。

私は

@Override 
      public void onResponse(Call<JSONResponse> call, Response<JSONResponse> response) { 
       JSONResponse jsonResponse = response.body(); 

       mRecyclerViewItems = new ArrayList<Object>(Arrays.asList(jsonResponse.getKonten())); 
       addNativeExpressAds(); 

       RecyclerView.Adapter adapter = new KontenAdapter(mRecyclerViewItems, getApplicationContext()); 
       mRecyclerView.setAdapter(adapter); 

setUpAndLoadNativeExpressAds(); // << ADD THIS METHOD HERE AND REMOVE THE OTHER CALLING 
      } 
+0

を頼むが、私はあなたの提案をしようとした後、アプリは空白でエラーはありません。 E/RecyclerViewを表示:アダプタが接続されていません。 logcatのレイアウトをスキップします。だから私は間違っている? –

0

あなたの問題はmRecyclerViewItemsは、ゼロベースの配列/コレクションであるということである使用することをお勧めします。しかしsetUpAndLoadNativeExpressAds()にあなたは何の要素を持っていない場合でも反復して、その後、こんにちは、あなたの答えのおかげで、要素の0

for (int i = 0; i <= mRecyclerViewItems.size(); i += ITEMS_PER_AD) { 
    final NativeExpressAdView adView = (NativeExpressAdView) mRecyclerViewItems.get(i); 
    .. 
} 

あなたがすべき代わり

for (int i = 0; i < mRecyclerViewItems.size(); i += ITEMS_PER_AD) { 
    .. 
} 
関連する問題