2017-05-29 2 views
0

Ich arbeite an Android-App, die Daten mit RecyclerView und Retrofit für die Analyse von JSON Url abrufen. Ich hatte folgendes Tutorial auf diesem GithubNativeExpressAdView java.lang.IndexOutOfBoundsException: Ungültiger Index 0, Größe ist 0

Mein Projekt auf Android Studio hat keine Fehler und ich bin in der Lage, die Anwendung auszuführen. Aber wenn ich die MainActivity öffne, stürzt es ab.

Fehler, die ich bekommen bin

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

Dies ist die folgende Zeile auf setUpAndLoadNativeExpressAds ist

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

Dies ist 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); 
    } 



} 

Dies ist 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; 
    } 
} 

Vielen Dank im Voraus! for (int i = 0; i <= mRecyclerViewItems.size(); i += ITEMS_PER_AD) { final NativeExpressAdView adView = (NativeExpressAdView) mRecyclerViewItems.get(i);

in verschiedenen Threads

Antwort

0

Du addNativeExpressAds() und aufrufen. So wird mRecyclerViewItems.get(i) vor seiner Initialisierung verwendet.

würde ich vorschlagen,

@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

Hallo, vielen Dank für Ihre Antwort, aber nachdem ich versuchen, Ihren Vorschlag die App ist leer ohne Fehler. Und zeigt E/RecyclerView: Kein Adapter angeschlossen; Layout auf Logcat überspringen. Also, wo ich falsch liege? –

0

Ihr Problem zu verwenden, ist, dass mRecyclerViewItems eine Null-basierter Array/Sammlung. Doch in setUpAndLoadNativeExpressAds() wird iterieren Sie, auch wenn Sie keine Elemente haben, und dann fragen Sie nach Element 0.

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

Sie sollten stattdessen

for (int i = 0; i < mRecyclerViewItems.size(); i += ITEMS_PER_AD) { 
    .. 
} 
Verwandte Themen