android - 为什么在横向到纵向切换后从详细 Activity 中按回显示空白屏幕?

标签 android android-fragments android-activity android-fragmentactivity android-lifecycle

下面是我正在使用的 MainActivity 类。该代码检查手机是横向还是纵向。如果它是纵向的,它将只显示主要 Activity 中的主要 fragment (主要 fragment 是 main_activity.xml 文件中的静态 fragment )。然后,如果单击“食谱”,它将打开一个带有自己 fragment 的详细 Activity 。如果手机处于横向模式,它将并排显示主要 fragment 和细节 fragment 。一切正常,但是当我按照以下步骤操作时,我得到的是白屏而不是主要 Activity :

程序:

  1. 切换到横向
  2. 切换回纵向
  3. 选择一个项目并等待详细 Activity 打开
  4. 按回
  5. 这里不是主 Activity 窗口,而是白屏

如果我不切换到横向,而只是从纵向模式开始,一切都很好。似乎切换到横向会导致问题,我无法弄清楚是什么。任何关于正在发生的事情或在哪里寻找的提示都将不胜感激。

public class MainActivity extends AppCompatActivity implements RecipesFragment.OnRecipeClickListener {

    private String RECIPE_PARCEL_KEY;
    private boolean mTwoPane;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RECIPE_PARCEL_KEY = getString(R.string.ParcelKey_RecipeParcel);
        if (findViewById(R.id.linearLayoutTwoPane) != null) {
            mTwoPane = true;
            if (savedInstanceState == null) {
                RecipeFragment recipeFragment = new RecipeFragment();
                FragmentManager fragmentManager = getSupportFragmentManager();
                fragmentManager.beginTransaction()
                        .add(R.id.recipeFrameForTwoPane, recipeFragment)
                        .commit();
            }
        } else {
            mTwoPane = false;
        }
    }

    @Override
    public void OnRecipeClick(Recipe recipe) {
        if (mTwoPane) {
            RecipeFragment recipeFragment = new RecipeFragment();
            recipeFragment.setRecipe(recipe);
            FragmentManager fragmentManager = getSupportFragmentManager();
            fragmentManager.beginTransaction()
                    .replace(R.id.recipeFrameForTwoPane, recipeFragment)
                    .commit();
        } else {
            Class destinationClass = DetailActivity.class;
            Intent intentToStartDetailActivity = new Intent(this, destinationClass);
            intentToStartDetailActivity.putExtra(RECIPE_PARCEL_KEY, recipe);
            startActivity(intentToStartDetailActivity);
        }
    }
}

编辑: 在下面添加 RecipeFragment 的代码:

public class RecipeFragment extends Fragment {

    private Recipe mRecipe;
    @BindView(R.id.tv_recipeName) TextView recipeNameTextView;

    public RecipeFragment(){
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.recipe_fragment,container,false);
        ButterKnife.bind(this,view);
        if(mRecipe!=null) {
            recipeNameTextView.setText(mRecipe.getName());
        }else{
            recipeNameTextView.setText(getString(R.string.messageSelectARecipe));
        }
        return view;
    }

    public void setRecipe(Recipe recipe){
        mRecipe = recipe;
    }
}

编辑: 我听从了@mt0s 的建议,为 fragment 和 Activity 创建了不同的背景颜色,最后将问题缩小到我的 recyclerview 适配器代码中的一行。我的适配器代码如下。在 loadInBackground()URL url = new URL(getString(R.string.URL_RecipeJSON)); 中,我得到一个 Fragment RecipesFragment{96e9b6a}未附加到 Activity 异常。我不明白为什么我会收到此异常以及解决此问题的最佳方法是什么。我是否在正确的 fragment 方法中放置了正确的代码(即 OnCreate 与 OnActivityCreated 与 OnCreateView 等)?

public class RecipesFragment extends Fragment
        implements RecipeAdapter.RecipeAdapterOnClickHandler,
        LoaderManager.LoaderCallbacks<ArrayList<Recipe>> {

    @BindView(R.id.rv_recipes) RecyclerView mRecyclerView;
    private RecipeAdapter mRecipeAdapter;
    private static final int LOADER_ID = 1000;
    private static final String TAG = "RecipesFragment";

    private OnRecipeClickListener mOnRecipeClickListener;

    public RecipesFragment(){
    }

    public interface OnRecipeClickListener {
        void OnRecipeClick(Recipe recipe);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.recipes_fragment, container, false);
        ButterKnife.bind(this, view);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setHasFixedSize(true);
        mRecipeAdapter = new RecipeAdapter(this);
        mRecyclerView.setAdapter(mRecipeAdapter);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getLoaderManager().initLoader(LOADER_ID, null, this);
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void OnClick(Recipe recipe) {
        mOnRecipeClickListener.OnRecipeClick(recipe);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try{
            mOnRecipeClickListener = (OnRecipeClickListener) context;
        } catch (ClassCastException e){
            Log.e(TAG, "onAttach: Host activity class must implement OnRecipeClickListener.");
        }
    }

    @Override
    public Loader<ArrayList<Recipe>> onCreateLoader(int i, Bundle bundle) {
        return new AsyncTaskLoader<ArrayList<Recipe>>(getActivity()) {

            @Override
            protected void onStartLoading() {
                super.onStartLoading();
                forceLoad();
            }

            @Override
            public ArrayList<Recipe> loadInBackground() {
                String response;
                ArrayList<Recipe> recipes = null;
                try {
                    URL url = new URL(getString(R.string.URL_RecipeJSON)); //***I get an exception here***
                    response = NetworkUtils.getResponseFromHttpUrl(url, getActivity());
                    recipes = RecipeJsonUtils.getRecipeFromJson(getActivity(), response);
                } catch (Exception e) {
                    Log.e(TAG, "loadInBackground: " + e.getMessage());
                }
                return recipes;
            }
        };
    }

    @Override
    public void onLoadFinished(Loader<ArrayList<Recipe>> loader, ArrayList<Recipe> recipes) {
        mRecipeAdapter.setRecipeData(recipes);
    }

    @Override
    public void onLoaderReset(Loader<ArrayList<Recipe>> loader) {

    }
}

最佳答案

我终于想通了问题和解决办法。问题是 RecipesFragment 类中的 AsyncTaskLoader 匿名类中的 onStartLoading() 每次 fragment 恢复时调用是否包含Loader 是否被调用。这导致了问题。我需要控制何时调用 onStartLoading() 并且我只希望它被调用 当且仅当正在初始化或重新启动封闭的 Loader 时。因此,我在 fragment 的 onPause() 中销毁了加载程序,并在 onResume() 中重新启动了它。因此,我将以下代码添加到 RecipesFragment 类中:

@Override
public void onPause() {
    super.onPause();
    getLoaderManager().destroyLoader(LOADER_ID);
}

@Override
public void onResume() {
    super.onResume();
    getLoaderManager().restartLoader(LOADER_ID, null, this);
}

我还从 onCreate() 中删除了 initLoader()。这样,每次恢复(或创建) fragment 时,都会调用 onStartLoading()。我试过了,它解决了我的问题。

关于android - 为什么在横向到纵向切换后从详细 Activity 中按回显示空白屏幕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48008780/

相关文章:

android - 以 Main Activity 命名的新 Android 项目而不是应用程序名称

javascript - 如何在 React Navigation 上调用抽屉内的函数而不是屏幕?

Android - 加载 fragment 实现

android - 抽屉导航默认 fragment

android - Android 的 Activity 生命周期如何与整个应用程序相关联?

android - 应用程序从深层链接启动,然后从启动器再次激活重新启动 Activity

android - ImageView 周围不需要的填充

android - 如何让安卓虚拟设备上网?

Android:启动快捷方式选择器

android - 如何向操作栏/工具栏添加后退按钮