Вводная активность как FragmentActivity не работает на определенных устройствах в соответствии с отчетом о предварительном запуске

Android новичок здесь. Любая помощь приветствуется. Поэтому я разместил свое приложение в консоли Google Play. У меня было несколько проблем, когда я делал предварительный отчет. Приложение не работает на 4 устройствах под управлением Android 6 и 7. Проблема заключается в подключении. Я показал класс OnBoardActivity и один из фрагментов OnboardingFragments (все они одинаковы, за исключением разных изображений в каждом макете перспективы (R.id.onboardingscreen_1, R.id.onboardingscreen_2 и т. д.).

Я вижу, что фатальный сбой связан с проблемой памяти «Вызвано: java.lang.OutOfMemoryError: не удалось выделить 132710412 байтов с 33554432 свободными байтами и 120 МБ до OOM». Строка, которая привлекла мое внимание в логарифме, заставляет меня думать, что это проблема OnBoardActivity:

"в Util.OnboardingFragment2.onCreateView(OnboardingFragment2.java:21)"

где 3 устройства выходят из строя.

Galaxy J7 терпит неудачу с этой разницей в логарифме:

"java.lang.IllegalStateException: Фрагмент уже добавлен: OnboardingFragment3{fe12a94 #2 id=0x7f0a0099}"

Я понятия не имею, почему мое приложение попытается выделить 132 МБ ??? Я не могу воссоздать ни один из них с помощью эмулятора. Когда я смотрю видео о сбое приложения, оно сразу запускается для этих 4 устройств. Он либо терпит неудачу при попытке подтянуть OnBoardActivity, либо при переходе к следующему или предыдущему фрагменту адаптации.

Я не уверен, что делать! Мне нужна какая-то краткая инструкция для первого запуска. Я уверен, что правильно запускаю OnBoardActivity (из MainActivity):

        prefs = getSharedPreferences(Util.APP_NAME, MODE_PRIVATE);

    if(!prefs.getBoolean("onboarding_complete", false)){
        Intent intent = new Intent(this, OnBoardActivity.class);
        startActivity(intent);

        finish();
        return;
    }

Журнал, который Google предоставляет для этих 4 сбоев:

<!-- language: lang-none -->
Caused by: android.view.InflateException: Binary XML file line #26: Error inflating class <unknown>
Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Constructor.newInstance0(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:430)
    at android.view.LayoutInflater.createView(LayoutInflater.java:645)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:787)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:727)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:858)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:861)
    at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:821)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:518)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:426)
    at Util.OnboardingFragment2.onCreateView(OnboardingFragment2.java:21)
    at android.support.v4.app.Fragment.performCreateView(Fragment.java:2346)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1428)
    at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
    at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
    at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
    at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
    at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
    at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2215)
    at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:649)
    at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:167)
    at android.support.v4.view.ViewPager.populate(ViewPager.java:1238)
    at android.support.v4.view.ViewPager.populate(ViewPager.java:1086)
    at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1616)
    at android.view.View.measure(View.java:19834)
    at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715)
    at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461)
    at android.view.View.measure(View.java:19834)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6164)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at android.view.View.measure(View.java:19834)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6164)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
    at android.view.View.measure(View.java:19834)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6164)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at com.android.internal.policy.DecorView.onMeasure(DecorView.java:692)
    at android.view.View.measure(View.java:19834)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2358)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1430)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1679)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1306)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6579)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
    at android.view.Choreographer.doCallbacks(Choreographer.java:683)
    at android.view.Choreographer.doFrame(Choreographer.java:619)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6316)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:872)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 132710412 byte allocation with 33554432 free bytes and 120MB until OOM
    at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:620)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:455)
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1152)
    at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:859)
    at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:710)
    at android.content.res.Resources.getDrawable(Resources.java:776)
    at android.content.Context.getDrawable(Context.java:530)
    at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:358)
    at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:198)
    at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:186)
    at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100)
    at android.support.v7.widget.AppCompatImageHelper.loadFromAttributes(AppCompatImageHelper.java:58)
    at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:77)
    at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:67)
    ... 58 more

Вот код:

public class OnBoardActivity extends FragmentActivity {

private ViewPager pager;
private SmartTabLayout indicatior;
private ButtonFlat skip;
private ButtonFlat next;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_onboarding);

    pager = findViewById(R.id.pager);
    indicatior = findViewById(R.id.indicator);
    skip = findViewById(R.id.skip);
    next = findViewById(R.id.next);

    FragmentStatePagerAdapter adapter = new FragmentStatePagerAdapter(getSupportFragmentManager()) {
        @Override
        public Fragment getItem(int position) {

            List<Fragment> f = getSupportFragmentManager().getFragments();

            for(int i=0; i<f.size(); i++){
                Log.d("Fragment Get", "Fragment: " + Integer.toString(i) + " "
                + f.get(i).getClass().getName());
            }

            Log.d("Fragment Pos", "Position: " + Integer.toString(position));

            switch (position) {
                case 0 :
                    Log.d("Fragment Ret", "Returning new OnboardingFragment1\n");
                    return new OnboardingFragment1();
                case 1 :
                    Log.d("Fragment Ret", "Returning new OnboardingFragment2\n");
                    return new OnboardingFragment2();
                case 2 :
                    Log.d("Fragment Ret", "Returning new OnboardingFragment3\n");
                    return new OnboardingFragment3();
                default: return null;
            }

        }


        @Override
        public int getCount() {
            return 3;
        }

        @Override
        public Parcelable saveState(){
            return null;
        }
    };

    pager.setAdapter(adapter);

    indicatior.setViewPager(pager);

    indicatior.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
        @Override
        public void onPageSelected(int position) {
            if(position == 2){
                skip.setVisibility(View.GONE);
                next.setText("Done");
            } else {
                skip.setVisibility(View.VISIBLE);
                next.setText("Next");
            }
        }
    });

    skip.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            finishOnboarding();
        }
    });

    next.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(pager.getCurrentItem() == 2){
                finishOnboarding();
            } else {
                pager.setCurrentItem(pager.getCurrentItem() + 1, true);
            }
        }
    });

}

private void finishOnboarding() {

    SharedPreferences preferences =
            getSharedPreferences(Util.APP_NAME, MODE_PRIVATE);

    preferences.edit()
            .putBoolean("onboarding_complete",true).apply();

    Intent intent = new Intent(this, MainActivity.class);
    startActivity(intent);
    finish();
}

}

public class OnboardingFragment1 extends Fragment {

@Override
public View onCreateView(@Nullable LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    setRetainInstance(true);

    return inflater != null ? inflater.inflate(
            R.layout.onboarding_screen1,
            container,
            false
    ) : null;
}

}

Надеюсь, кто-то может помочь! Спасибо за чтение! -Мэтт


comment
Ваш вопрос похож на этот: stackoverflow.com/questions/33182433/   -  person VIN    schedule 08.08.2018
comment
Я нашел решение, осмотревшись и найдя несколько полезных статей о том, как работают фрагменты. Кажется, что у FragmentStatePageAdapter могут быть некоторые проблемы с попыткой создать представления, которые, по его мнению, были удалены, но на самом деле это не так. Обходной путь — это простое изменение OnboardingFragment: ‹br/› return getView() !=null ? getView(): inflater.inflate(R.layout.onboarding_screen1, container, false);   -  person lil_matthew    schedule 08.08.2018
comment
Пожалуйста, обновите свой комментарий до ответа (и примите его), это поможет будущим людям. Я бы проголосовал за это.   -  person Nick Fortescue    schedule 09.08.2018
comment
Сделаю! Спасибо!   -  person lil_matthew    schedule 10.08.2018


Ответы (1)


В моем комментарии я нашел решение после долгих исследований фрагментов. Иногда FragmentStatePageAdapter пытается увеличить представления, которые, по его мнению, были удалены, но на самом деле еще не удалены. Теперь он отлично работает, изменив OnboardingFragment на:

public class OnboardingFragment1 extends Fragment {
    @Override
    public View onCreateView(@Nullable LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        return getView() !=null ? getView(): inflater.inflate(R.layout.onboarding_screen1, container, false);
}
person lil_matthew    schedule 10.08.2018