gpt4 book ai didi

java - IndexOutOfBoundsException 导致 Android 应用程序崩溃

转载 作者:行者123 更新时间:2023-12-02 02:53:28 26 4
gpt4 key购买 nike

我正在单击上一个 Activity 的 View 列表中的一个项目。此 Activity 应该获取该对象并显示该对象的特征。当我单击 viewList 时,应用程序崩溃。这是日志猫:

04-16 19:37:09.183 22696-22696/cs4326.cook4me E/AndroidRuntime: FATAL EXCEPTION: main
Process: cs4326.cook4me, PID: 22696
java.lang.RuntimeException: Unable to start activity ComponentInfo{cs4326.cook4me/cs4326.cook4me.RecipeInstructActivity}: java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.ArrayList.add(ArrayList.java:457)
at cs4326.cook4me.RecipeInstructActivity.onCreate(RecipeInstructActivity.java:45)
at android.app.Activity.performCreate(Activity.java:6679)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6119) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

这是相应的 Activity 代码(错误显示在第 45 行):

package cs4326.cook4me;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;

public class RecipeInstructActivity extends FragmentActivity {

private static final String TAG = "RecipeInstructActivity";
/**
* Identifier for the example fragment.
*/
public static final int FRAGMENT_COMPLETE = 1;
public static final int FRAGMENT_STEPPED = 2;

/**
* The adapter definition of the fragments.
*/
private FragmentPagerAdapter _fragmentPagerAdapter;

/**
* The ViewPager that hosts the section contents.
*/
private ViewPager _viewPager;

/**
* List of fragments.
*/
private List<Fragment> _fragments = new ArrayList<>();

@Override
protected void onCreate(final Bundle savedInstanceState) {
Log.d(TAG, "onCreate:");
super.onCreate(savedInstanceState);

this.setContentView(R.layout.activity_main);

// Each fragment to our list.
this._fragments.add(FRAGMENT_COMPLETE, new CompleteInstructionFragment());
this._fragments.add(FRAGMENT_STEPPED, new SteppedInstructionFragment());

// Setup the fragments, defining the number of fragments, the screens and titles.
this._fragmentPagerAdapter = new FragmentPagerAdapter(this.getSupportFragmentManager()){
@Override
public int getCount() {
return RecipeInstructActivity.this._fragments.size();
}
@Override
public Fragment getItem(final int position) {
return RecipeInstructActivity.this._fragments.get(position);
}
@Override
public CharSequence getPageTitle(final int position) {
// Define titles for each fragment.
switch (position) {
case FRAGMENT_COMPLETE:
return "Complete Recipe";
case FRAGMENT_STEPPED:
return "Step-by-Step";
default:
return null;
}
}
};

this._viewPager = (ViewPager) this.findViewById(R.id.pager);
this._viewPager.setAdapter(this._fragmentPagerAdapter);

// Set the default fragment.
this.openFragment(FRAGMENT_COMPLETE);
}

/**
* Open the specified fragment.
* @param fragment
*/
public void openFragment(final int fragment) {
this._viewPager.setCurrentItem(fragment);
}

/**
* Get the fragment object for the specified fragment.
* @param fragment
* @return
*/
public Fragment getFragment(final int fragment) {
return this._fragments.get(fragment);
}
}

这是父 viewList Activity 的代码:

package cs4326.cook4me;

import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;

import java.util.Comparator;
import java.util.TreeSet;

public class RecipesActivity extends AppCompatActivity implements AdapterView.OnItemClickListener{
private static final String TAG = "RecipesActivity";
private DatabaseReference databaseReference;
private ListView mainListView ;
private ArrayAdapter<String> listAdapter ;
private TreeSet<Recipe> allRecipeData;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recipes);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

//Initialize reference to database
databaseReference = FirebaseDatabase.getInstance().getReference();
//Initialize recipe data set
allRecipeData = new TreeSet<Recipe>(new Comparator<Recipe>() {
@Override
public int compare(Recipe o1, Recipe o2) {
return o1.getTitle().compareToIgnoreCase(o2.getTitle());
}
});
// Create ArrayAdapter
listAdapter = new ArrayAdapter<String>(this, R.layout.row_layout);
//Create query for recipes
Query recipesReference = databaseReference.child("recipes").orderByChild("title");
recipesReference.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
// Get Recipe object and use the values to update the UI
Recipe recipe = dataSnapshot.getValue(Recipe.class);
listAdapter.add(recipe.getTitle());
allRecipeData.add(recipe);
Log.d(TAG, "loadRecipe:onChildAdded");
}

@Override
public void onChildChanged(DataSnapshot dataSnapshot, String previousName) {
// Get Recipe object and use the values to update the UI
Recipe recipe = dataSnapshot.getValue(Recipe.class);
listAdapter.remove(previousName);
listAdapter.add(recipe.getTitle());
Log.d(TAG, "loadRecipe:onChildChanged");
}

@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
// Get Recipe object and use the values to update the UI
Recipe recipe = dataSnapshot.getValue(Recipe.class);
listAdapter.remove(recipe.getTitle());
allRecipeData.remove(recipe);
Log.d(TAG, "loadRecipe:onRemoved");
}

@Override
public void onChildMoved(DataSnapshot dataSnapshot, String olden) {
// Get Recipe object and use the values to update the UI
Recipe recipe = dataSnapshot.getValue(Recipe.class);
listAdapter.remove(olden);
listAdapter.add(recipe.getTitle());
Log.d(TAG, "loadRecipe:onChildMoved");
}

@Override
public void onCancelled(DatabaseError databaseError) {
// Getting Recipe failed, log a message
Log.w(TAG, "loadRecipe:onCancelled", databaseError.toException());
}
});

// Find the ListView resource.
mainListView = (ListView) findViewById( R.id.listViewRecipes );
//Add list items!
mainListView.setAdapter( listAdapter );

//TODO: Make it so clicking / tapping on each item redirects to Recipe
mainListView.setOnItemClickListener(this);


//Floating login button
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent transfer = new Intent(RecipesActivity.this, LoginActivity.class);
startActivity(transfer);
}
});

//If you type, it will automatically start searching
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
//Floating search button
FloatingActionButton floatingSearch = (FloatingActionButton) findViewById(R.id.search_recipes);
floatingSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onSearchRequested();
}
});

//Redirects back to Main Menu if press up button
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

public void onItemClick(AdapterView<?> l, View v, int position, long id) {
Log.d(TAG, "You clicked " + listAdapter.getItem(position));
String nameOf = listAdapter.getItem(position);
Recipe selectedRecipe = new Recipe();
// Then you start a new Activity via Intent
Intent specialTransfer = new Intent(RecipesActivity.this, RecipeInstructActivity.class);
for (Recipe r : allRecipeData) {
if (r.getTitle().equals(nameOf)) {
selectedRecipe = r;
}
}
//Pass selected recipe
specialTransfer.putExtra("recipe_object", selectedRecipe);
startActivity(specialTransfer);

}

}

这是 AndroidManifest.XML:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cs4326.cook4me">

<uses-permission android:name="android.permission.INTERNET" />

<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

<application
android:allowBackup="true"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light">
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LoginActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cs4326.cook4me.MainActivity" />
</activity>

<activity
android:name=".RegisterActivity"
android:label="Register User"
android:parentActivityName=".LoginActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cs4326.cook4me.LoginActivity" />
</activity>

<activity
android:name=".ProfileActivity"
android:label="User profile"
android:parentActivityName=".LoginActivity" />
<activity
android:name=".SettingsActivity"
android:label="@string/title_activity_settings"
android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cs4326.cook4me.MainActivity" />
</activity>
<!--
<activity
android:name=".RecipeFragment"
android:label="@string/title_activity_recipe_fragment"
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name=".ProfileFragment"
android:label="@string/title_activity_profile_fragment"
android:theme="@style/AppTheme.NoActionBar"></activity>
-->
<activity
android:name=".RecipesActivity"
android:label="@string/title_activity_recipes"
android:parentActivityName=".MainActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cs4326.cook4me.MainActivity" />
<meta-data android:name="android.app.default_searchable"
android:value=".SearchRecipeActivity" />
</activity>
<activity
android:name=".CookingTerminologyActivity"
android:label="@string/title_activity_cooking_terminology"
android:parentActivityName=".MainActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cs4326.cook4me.MainActivity" />
</activity>
<activity
android:name=".TermActivity"
android:label="@string/title_activity_term"
android:parentActivityName=".CookingTerminologyActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cs4326.cook4me.CookingTerminologyActivity" />
</activity>

<activity
android:name=".SearchRecipeActivity"
android:label="@string/title_activity_search_recipe"
android:parentActivityName=".RecipesActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cs4326.cook4me.RecipesActivity" />
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data android:name="android.app.searchable"
android:resource="@xml/searchable"/>
</activity>

<activity
android:name=".RecipeInstructActivity"
android:parentActivityName=".RecipesActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="cs4326.cook4me.RecipeInstructActivity" />

</activity>
</application>

</manifest>

最佳答案

问题 1:静态初始化

private List<Fragment> _fragments = new ArrayList<>(); //be careful doing this!

字段初始化在 Android Activity 和 fragment 中效果不佳,因为它们的生命周期是受控制的。虽然在这种情况下它不会导致问题,但如果您在字段初始化中使用 findViewById(int id) 或其他此类方法,则可能会遇到麻烦。在 Activity 和 Fragment 的生命周期真正清晰之前,最好避免将代码放入 onCreate()onResume() 回调中(根据需要)。

问题 2:滚动我们自己的 FragmentManager

在此代码中, fragment 被缓存在列表中。没有必要这样做 - 这是 FragmentManager 缓存 fragment 的工作。

此外,方法 FragmentPagerAdapter#getItem() 应该用于实例化,而不是从列表中检索。这并不是你的错——我认为这个方法的命名很糟糕。它的真正含义更像是“createItem()”,它应该看起来更像这样:

    this._fragmentPagerAdapter = new FragmentPagerAdapter(this.getSupportFragmentManager()){
@Override
public int getCount() {
return RecipeInstructActivity.this._fragments.size();
}
@Override
public Fragment getItem(final int position) {
switch (position) {
case FRAGMENT_COMPLETE:
return new CompleteInstructionFragment();
case FRAGMENT_STEPPED:
return new StepByStepFramgment();
}

如果可能的话,最好将所有内容留给 ViewPager。如果您不能并且需要自己操作 fragment ,那么当您添加 fragment 时,请使用重载,该重载允许您在完成事务时向 fragment 添加标签,然后当您需要 fragment 的句柄时,您可以使用 findFragmentByTag 来检索它。

关于java - IndexOutOfBoundsException 导致 Android 应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43443726/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com