【问题标题】:What is going on with my Android Navigation drawer activity?我的 Android 导航抽屉活动发生了什么?
【发布时间】:2016-08-08 11:59:12
【问题描述】:

我正在构建一个 OpenGL 动态壁纸。我决定在我的主要活动中使用导航抽屉,因为用户可以访问很多功能。

问题/问题 如果我按下“硬件”后退按钮以正常关闭应用程序,则显示的初始片段只会刷新并且应用程序永远不会关闭。如果我点击主页按钮并返回应用程序,一切都是黑屏。我在整个 Google 中进行了搜索,认为也许我没有正确销毁 MainActivity 或寻找终止片段的方法。我尝试在主要活动的 onDestroy 方法中调用 finish()。我已经尝试在我在网上找到的每个帖子的每个片段 onDetach 方法中使用片段管理器中的 remove 方法。没有任何效果。我难住了。我在 onDestroy 方法和片段 onDetach 方法的主要活动中设置了调试点,没有产生错误或给出任何信息。在这一点上,我一无所知。这是我的 MainActivity 类。

    public class MainActivity extends AppCompatActivity implements OnNavigationItemSelectedListener, OnPostSelectedListener{

    FragmentManager mFragmentManager;
    FragmentTransaction mFragmentTransaction;
    TextView usrTag, tagrEmail;
    CircleImageView tagrPic;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        mFragmentManager = getSupportFragmentManager();
        mFragmentTransaction = mFragmentManager.beginTransaction();
        mFragmentTransaction.add(R.id.cLMain, new PreviewFragment()).addToBackStack("PreviewFragment").commit();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        View header = navigationView.getHeaderView(0);
        usrTag = (TextView)header.findViewById(R.id.usrName);
        tagrEmail = (TextView)header.findViewById(R.id.usrEmail);
        tagrPic = (CircleImageView)header.findViewById(R.id.usrImg);

        Log.i("MainActivity: ", "User Photo: " + getProfilePic(this));

        usrTag.setText(getUserName(getBaseContext()));
        tagrEmail.setText(getUserEmail(getBaseContext()));
        GlideUtils.loadProfileIcon(getProfilePic(getBaseContext()), tagrPic);

    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();


        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        Fragment fragment = null;
        Class fragmentClass = null;
        int id = item.getItemId();

        if (id == R.id.nav_home) {
            fragmentClass = PreviewFragment.class;
        } else if (id == R.id.nav_custom) {
            startCustomLabelCreator();
        } else if (id == R.id.nav_mylabels) {

        } else if (id == R.id.nav_commLabels) {
            fragmentClass = PostsFragment.class;
        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        try {
            fragment = (Fragment) fragmentClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Insert the fragment by replacing any existing fragment
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.cLMain, fragment).commit();

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    public void startCustomLabelCreator(){
        Intent cLC = new Intent(getBaseContext(), CreateLabel.class);
        startActivity(cLC);
    }

    @Override
    public void onPostComment(String postKey) {

    }

    @Override
    public void onPostLike(String postKey) {

    }

    @Override
    public void onPhotoSelected(String photoUrl) {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        finish();
    }
}

我的片段

    public class PostsFragment extends Fragment implements ConfirmSelectedPhotoListener{

    public static final String TAG = "PostsFragment";
    private static final String KEY_LAYOUT_POSITION = "layoutPosition";
    private int mRecyclerViewPosition = 0;
    private OnPostSelectedListener mListener;


    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter<PostViewHolder> mAdapter;

    public PostsFragment() {
        // Required empty public constructor
    }

    public static PostsFragment newInstance() {
        PostsFragment fragment = new PostsFragment();
        return fragment;
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_posts, container, false);
        rootView.setTag(TAG);

        mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        linearLayoutManager.setReverseLayout(true);
        linearLayoutManager.setStackFromEnd(true);
        mRecyclerView.setLayoutManager(linearLayoutManager);

        Log.d(TAG, "Restoring recycler view position (all): " + mRecyclerViewPosition);
        Query allPostsQuery = FirebaseUtil.getPostsRef();
        mAdapter = getFirebaseRecyclerAdapter(allPostsQuery);
        mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                super.onItemRangeInserted(positionStart, itemCount);
                // TODO: Refresh feed view.
            }
        });


        mRecyclerView.setAdapter(mAdapter);
    }

    private FirebaseRecyclerAdapter<Post, PostViewHolder> getFirebaseRecyclerAdapter(Query query) {
        return new FirebaseRecyclerAdapter<Post, PostViewHolder>(
                Post.class, R.layout.post_item, PostViewHolder.class, query) {
            @Override
            public void populateViewHolder(final PostViewHolder postViewHolder,
                                           final Post post, final int position) {
                setupPost(postViewHolder, post, position, null);
            }

            @Override
            public void onViewRecycled(PostViewHolder holder) {
                super.onViewRecycled(holder);
//                FirebaseUtil.getLikesRef().child(holder.mPostKey).removeEventListener(holder.mLikeListener);
            }
        };
    }

    private void setupPost(final PostViewHolder postViewHolder, final Post post, final int position, final String inPostKey) {
        postViewHolder.setPhoto(post.getThumb_url());
        Log.d(TAG, post.getThumb_url());
        postViewHolder.setText(post.getText());
        postViewHolder.setTimestamp(DateUtils.getRelativeTimeSpanString(
                (long) post.getTimestamp()).toString());
        final String postKey;
        if (mAdapter instanceof FirebaseRecyclerAdapter) {
            postKey = ((FirebaseRecyclerAdapter) mAdapter).getRef(position).getKey();
        } else {
            postKey = inPostKey;
        }

        Author author = post.getAuthor();
        postViewHolder.setAuthor(author.getFull_name(), author.getUid());
        postViewHolder.setIcon(author.getProfile_picture(), author.getUid());

        ValueEventListener likeListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                postViewHolder.setNumLikes(dataSnapshot.getChildrenCount());
                if (dataSnapshot.hasChild(FirebaseUtil.getCurrentUserId())) {
                    postViewHolder.setLikeStatus(PostViewHolder.LikeStatus.LIKED, getActivity());
                } else {
                    postViewHolder.setLikeStatus(PostViewHolder.LikeStatus.NOT_LIKED, getActivity());
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        };
        FirebaseUtil.getLikesRef().child(postKey).addValueEventListener(likeListener);
        postViewHolder.mLikeListener = likeListener;

        postViewHolder.setPostClickListener(new PostViewHolder.PostClickListener() {
            @Override
            public void showComments() {
                Log.d(TAG, "Comment position: " + position);
                mListener.onPostComment(postKey);
            }

            @Override
            public void toggleLike() {
                Log.d(TAG, "Like position: " + position);
                mListener.onPostLike(postKey);
            }

            @Override
            public void savePhotoUrl() {
                //mListener.onPhotoSelected(post.getFull_url());
                showLabelConfirm(post.getFull_url());
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mAdapter != null && mAdapter instanceof FirebaseRecyclerAdapter) {
            ((FirebaseRecyclerAdapter) mAdapter).cleanup();
        }
    }


    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Save currently selected layout manager.
        int recyclerViewScrollPosition = getRecyclerViewScrollPosition();
        Log.d(TAG, "Recycler view scroll position: " + recyclerViewScrollPosition);
        savedInstanceState.putSerializable(KEY_LAYOUT_POSITION, recyclerViewScrollPosition);
        super.onSaveInstanceState(savedInstanceState);
    }

    private int getRecyclerViewScrollPosition() {
        int scrollPosition = 0;
        // TODO: Is null check necessary?
        if (mRecyclerView != null && mRecyclerView.getLayoutManager() != null) {
            scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
                    .findFirstCompletelyVisibleItemPosition();
        }
        return scrollPosition;
    }

    @Override
    public void onSelectedPhoto(String selectPhoto) {
        mListener.onPhotoSelected(selectPhoto);
    }

    public interface OnPostSelectedListener {
        void onPostComment(String postKey);
        void onPostLike(String postKey);
        void onPhotoSelected(String photoUrl);
    }

    private void showLabelConfirm(String uriBmp) {
        FragmentManager fm = getFragmentManager();
        PhotoDialogFragment editNameDialogFragment = PhotoDialogFragment.newInstance(uriBmp);
        // SETS the target fragment for use later when sending results
        editNameDialogFragment.setTargetFragment(PostsFragment.this, 300);
        editNameDialogFragment.show(fm, "fragment_edit_name");
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnPostSelectedListener) {
            mListener = (OnPostSelectedListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnPostSelectedListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }
}

第二个片段:

    public class PreviewFragment extends RajBaseFragment {


    @Override
    public ISurfaceRenderer createRenderer() {
        return new PreviewRenderer(getContext());
    }


}

延伸:

    public abstract class RajBaseFragment extends Fragment implements IDisplay, View.OnClickListener {


    protected FrameLayout mLayout;
    protected ISurface mRajawaliSurface;
    protected ISurfaceRenderer mRenderer;

    public RajBaseFragment(){

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        // Inflate the view
        mLayout = (FrameLayout) inflater.inflate(getLayoutID(), container, false);

        mLayout.findViewById(R.id.relative_layout_loader_container).bringToFront();

        // Find the TextureView
        mRajawaliSurface = (ISurface) mLayout.findViewById(R.id.rajwali_surface);

        // Create the loader


        mRenderer = createRenderer();
        onBeforeApplyRenderer();
        applyRenderer();
        return mLayout;
    }

    protected void onBeforeApplyRenderer() {

    }

    protected void applyRenderer() {
        mRajawaliSurface.setSurfaceRenderer(mRenderer);
    }

    @Override
    public void onClick(View v) {

    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        if (mLayout != null)
            mLayout.removeView((View) mRajawaliSurface);
    }

    @Override
    public int getLayoutID() {
        return R.layout.rajawali_textureview_fragment;
    }




}

到目前为止,我已经尝试了以下所有建议,并且在 MainActivity 的 onCreate 方法中设置的主要片段在按下后退按钮而不是应用退出/关闭时仍会刷新/重新加载。

【问题讨论】:

  • 检查是否在按下返回按钮时调用 super.onBackPressed() 语句?
  • @SandeepSharma 我如何在 logcat 中检查或查看?
  • 您可以将调试器点附加到此语句。您可能会想到的另一个解决方案是正确处理片段的可聚焦视图。他们也可能会导致问题,如@Hiren Patel 回答中的stackoverflow.com/questions/18755550/… 所建议的那样。
  • 如果这没有帮助,请发布您的片段的相关代码。
  • @SandeepSharma 请看我的编辑

标签: java android android-fragments navigation-drawer


【解决方案1】:

在您的onNavigationItemSelected 方法中,您将用fragment 替换当前片段,即使fragment 为空,这具有未定义的效果。你不应该那样做。

一种解决方法是替换此代码块:

try {
  fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
  e.printStackTrace();
}

用这个:

if (fragmentClass != null) {
  fragment = fragmentClass.newInstance();
  FragmentManager fragmentManager = getSupportFragmentManager();
  fragmentManager.beginTransaction().replace(R.id.cLMain, fragment).addToBackStack().commit();
}

(然后在此点下方省略片段事务)。

另外,在onDestroy 方法中有一个对finish 的调用,这可能不是导致问题的原因,但应该删除,因为它在那里没有任何意义。

【讨论】:

  • 正如另一个答案中所指出的,您也错误地使用了addToBackStack。我这里改了把事务添加到后台栈的答案,但是你在onCreate设置初始fragment的时候也不需要添加到后台栈。
【解决方案2】:
 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
          switch (item.getItemId()) {
          case android.R.id.home:
                 onBackPressed();
                 break;
            }
          return true;
  }

用我的替换你的 onOptionsItemSelected()。

【讨论】:

    【解决方案3】:

    不要将您的第一个片段包含在 backstack 中。

    尝试更改不带addToBackStack 的片段事务行代码 如下:

    mFragmentTransaction.add(R.id.cLMain, new PreviewFragment()).commit();
    

    使用addToBackStack 添加片段时,这允许返回 添加片段的导航。由于后台堆栈中的片段, empty(black) 将显示活动布局。

    如果在 FragmentManager 中没有找到任何 Fragment,则将 onBackPressed() 更改为以下自动关闭应用程序:

        @Override
    public void onBackPressed() {
        if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
            this.finish();
        } else {
            getSupportFragmentManager().popBackStack();
        }
    }
    

    您还可以在以下链接中看到一些类似的 Q/A,这有助于您获得更多解决问题的想法:

    Fragment pressing back button

    In Fragment on back button pressed Activity is blank

    Transaction of fragments in android results in blank screen

    它解决了我的黑屏问题。希望对你有帮助。

    【讨论】:

    • 我试过了,按下后退按钮时它仍然刷新/重新加载主要片段
    【解决方案4】:

    试试这个代码,希望对你有帮助,带上你需要的东西。另外,尝试在 Android Studio 中运行这个项目,它可以工作。

    https://github.com/asifali22/Navigation_Health/blob/master/app/src/main/java/com/thenewboston/mynavigation/MainActivity.java

    【讨论】:

    • 你试过了吗?
    • 谢谢。该信息很有帮助。
    【解决方案5】:

    当用户按下返回按钮时,它会检查片段管理器的后台堆栈,如果后台堆栈实体计数大于 0(这意味着后台堆栈中有一个片段),它将 popBackStack 否则它将完成活动。

    如果您将初始片段添加到 backstack,当用户按下返回按钮时,他们会看到一个空白屏幕。

    此外,当您初始化活动时,如果您需要放置片段,最好检查保存的实例状态是否为空。这里我修改了你的部分代码。

    if(savedInstanceState == null){
            mFragmentManager = getSupportFragmentManager();
            mFragmentTransaction = mFragmentManager.beginTransaction();
            mFragmentTransaction.add(R.id.cLMain, new PreviewFragment()).commit();
    }
    

    我希望这会对你有所帮助。如果您仍有问题,请告诉我。

    祝你好运。

    【讨论】:

    • 我尝试添加它,它仍然会刷新 PreviewFragment 或按下后退按钮时设置为主要的任何片段。
    【解决方案6】:

    ISurface 创建子类并像这样覆盖onKeyDown 方法

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Log.e("Custom View", "onKeyDown");
        //return super.onKeyDown(keyCode, event);
        return false;
    }
    

    【讨论】:

      【解决方案7】:

      可能与生命周期有关... 尝试使用GLSurfaceView。我相信你想要的更容易,特别适用于 OpenGL 渲染,并且有很多关于它的信息。 Exampleslifecycleothers 中。让我知道是否有帮助。如果没有,请提供更多信息。

      【讨论】:

      • OpenGL 部分没有任何问题。这是导航抽屉和片段的主要活动。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-22
      • 2014-10-29
      • 1970-01-01
      • 2020-06-02
      • 1970-01-01
      • 1970-01-01
      • 2013-09-12
      相关资源
      最近更新 更多