Что происходит с моей активностью в приложении Android Navigation?
Я создаю живые обои OpenGL. Я решил использовать навигационный ящик в своем основном действии, так как есть много функций, к которым у пользователя будет доступ.
Проблема/проблема
Если я нажму кнопку "hardware" назад, чтобы нормально закрыть приложение, начальный фрагмент, который отображается только что обновляется, и приложение никогда не закрывается. Если я нажму кнопку "домой" и вернусь в приложение, все будет черным экраном. Я искал всюду по Google, думая, что, возможно, я не уничтожаю MainActivity правильно или для прекращения фрагмента. Я попытался вызвать finish() в основном методе onDestroy. Я попытался использовать метод remove из диспетчера фрагментов в каждом фрагменте метода onDetach для сообщений, которые я нашел в Интернете. Ничего не сработало. Я в тупике. Я установил точки отладки в основном действии по методу 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, по-прежнему обновляется/перезагружается при нажатии кнопки "Назад", а не при выходе/закрытии приложения.
Ответы
Ответ 1
В вашем методе onNavigationItemSelected
вы заменяете текущий фрагмент на fragment
даже в случаях, когда fragment
имеет значение null, которое имеет undefined эффекты. Вы не должны этого делать.
Одно исправление заключается в замене этого кодового блока:
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();
}
(а затем опустить транзакцию фрагмента ниже этой точки).
Кроме того, есть вызов finish
в методе onDestroy
, который, вероятно, не вызывает проблемы, но должен быть выведен, потому что он не имеет никакого смысла там.
Ответ 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
, это позволяет вернуться навигация для добавления фрагмента. Из-за фрагмента в backstack, пустой (черный).
Измените onBackPressed()
, как показано ниже, которое автоматически закрывает приложение после того, как в FragmentManager не обнаружен какой-либо фрагмент:
@Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
this.finish();
} else {
getSupportFragmentManager().popBackStack();
}
}
Также вы можете увидеть некоторые похожие Q/A ниже ссылки, которые помогут вам получить больше идей для решения вашей проблемы:
Отправка фрагмента назад
В нажатой кнопке "Фрагмент на задней панели" Действие пустое
Транзакция фрагментов в андроидах приводит к пустым экранам
Он решил мою проблему с пустым экраном. Надеюсь, это поможет вам.
Ответ 4
Попробуйте этот код, надейтесь, что это поможет вам, возьмите необходимые вещи, которые вам нужны. Кроме того, попробуйте запустить этот проект в студии Android, он работает.
https://github.com/asifali22/Navigation_Health/blob/master/app/src/main/java/com/thenewboston/mynavigation/MainActivity.java
Ответ 5
Когда пользователь нажимает кнопку "Назад", он проверяет стоп-память менеджера фрагментов и, если количество экземпляров backstack больше 0 (это означает, что есть фрагмент в backstack), он будет popBackStack, иначе он завершит активность.
Если вы добавите свой первоначальный фрагмент в стопку, когда пользователь нажмет кнопку "Назад", он увидит пустой экран.
Также, когда вы начинаете свою деятельность, если вам нужно поместить фрагмент, лучше всего проверить, было ли состояние сохраненного экземпляра нулевым. Здесь я модифицировал часть кода.
if(savedInstanceState == null){
mFragmentManager = getSupportFragmentManager();
mFragmentTransaction = mFragmentManager.beginTransaction();
mFragmentTransaction.add(R.id.cLMain, new PreviewFragment()).commit();
}
Надеюсь, это поможет вам. Если у вас все еще есть проблема, дайте мне знать.
Удачи.
Ответ 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, и есть много информации об этом. Примеры, жизненный цикл среди другие. Дайте мне знать, если поможете. Если нет, просьба предоставить дополнительную информацию.