Pull to refresh

Comments 32

Как вариант сойдёт, но если фрагментов будет очень много, то создаются огромные выборки статической переменной и начитаешь путаться, какое значение отвечает за какой фрагмент.

Откройте для себя правило: никаких магический чисел в коде. И проблема уйдет сама собой.
Проблема 5

Проблема очень эстетично решается через создание синглтона главной активити, в которой происходит управление фрагментами, и уже через синглтон вызывать открытие нового фрагмента
Проблема 2

Ну тут обычно все наоборот, все обычно начинают с SharedPreferences, а потом уходят в сторону БД, как бы логично от простого к сложному. Просто нужно понимать разницы, SharedPreferences предназначен больше сохранения состояний/настроек, можно конечно его и под все подряд использовать, но это не есть правильно.
Даже если быть самоучкой то первый поиск в гугле приводит к SharedPreferences https://www.google.se/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5+%D0%B2+android+java
Проблема очень эстетично решается через создание синглтона главной активити, в которой происходит управление фрагментами, и уже через синглтон вызывать открытие нового фрагмента

Именно это я и описывал дальше.
Ещё один вариант, предлагаемый документацией Google — это через объект интерфейса, то есть фрагмент обрабатывает нажатие на свои кнопки и при нажатии создаётся объект интерфейса, который реализует активность
… Умейте дочитать до конца.
Просто вы завуалировали ответ, судя по которому может несколько решений в голову прийти. Я же конкретизировал метод который эстетично подходит для решения данной проблемы, и является общепринятым.
Просто вы пишите статью о том с какими проблемами столкнулись и какие решения приняли, и писать это в общих чертах не есть правильно, немного конкретики не помешает.
Вообще многие описанные проблемы не считая проблемы №6 очень банальны, и если вы пришли в андроид с любого другого языка программирования, то многие эти проблемы должны отпасть сами собой, потому что принципы одни и те же, можно легко на гуглить решение для конкретного языка/платформы
К слову дочитал статью до конца, некоторые банальные моменты даже перечитал
А что вы отображаете во фрагментах можно узнать? Просто судя по вашему предыдущему посту, у вас приложения на 3-4 активити без какой-то сложной графики. Не могу понять, что там может тормозить.
System.out.println(«MainActivity:onBackPressed()»);

Ну не так же логи выводятся в андроиде то) Вот, почитайте.
if (idTheCurrentFragment == 4) {

Используйте константы же. В этих цифрах запутаться легче легкого.

А вообще, большая часть проблем решилась бы сама собой, если бы вы просто ушли от фрагментов, от них реально получить пользу можно только в очень редких случаях, а в основном одни проблемы.
приложения на 3-4 активити без какой-то сложной графики. Не могу понять, что там может тормозить.

Тут наверное дело не в мощности, а в версии андроид. На телефоне под андроид 4.1 видно как создаётся ещё одно окно. И ещё я сравнивал по ОЗУ. Фрагменты экономнее.
И ещё я сравнивал по ОЗУ. Фрагменты экономнее.

Исключительно на момент старта. Если архитектура правильная то разницы вы абсолютно никакой не увидите. К примеру переделывал свой, довольно большой проект (более 30 уникальных активити) на фрагменты, переделывал исключительно из-за навигации. Так вот по производительности особую разницу я не заметил. Если у вас ощутимо тормозит запуск новой активности, то стоит обратить внимание где именно происходит утечка, видимо что то в основном потоке нагрузочное стартует
К слову, фрагмент на то и называется фрагментом, что он заменяет часть GUI, за новое окно отвечает именно Activity. Нужно понимать разницу и разделять эти понятия, каждый метод предназначен для своей задачи
На телефоне под андроид 4.1 видно как создаётся ещё одно окно.

До андроида 3.0 вообще жили на одних активити, и ничего, делали плавные приложения)
И ещё я сравнивал по ОЗУ. Фрагменты экономнее.

Пользователи себе телефоны с 3+гб оперативы покупают, чтобы мы им по 5-10мб экономили чтоли?)

Можно увидеть Методы onCreate и onStart одного из ваших фрагментов? Просто интересно что вы там загружаете.
К примеру, если вы там каждый раз дергаете SharedPref подобным образом
sharedPref = context.getSharedPreferences(«RatFile», MODE_PRIVATE);

это будет давать лаг.
SharedPref лучше вообще инициализировать один раз при запуске, через контекст приложения, а потом обращаться к уже созданному объекту.
Я думаю SharedPref тут меньше из зол, он даже не даст настолько ощутимого эффекта о котором говорит автор, там что-то по серьезднее запускается. Еще подобный косяк кстати был замечен на сдк >=20, там в анимации активити при переходах иногда бывают затупы, ощущение что они искуственные чтобы перевести все на фрагменты
Ну а чо, когда 3 андроид вышел, все и так кинулись использовать эти фрагменты. Казалось, что делать 1 активити и 150 фрагментов в нем, это спасение. Потом правда попустило)
Если мне память не изменяет, то 3 андроид только для планшетов был. И там гугл сам чуть ли не настаивал на использовании фрагментов. Просто там дизайн в приложениях был таков что менялись части активити, а не вся активити. То есть фрагменты изначально и были созданы для того что бы изменить часть активити не прибегая к полной ее перезагрузки (заменить ее фрагмент), а так же фрагменты были и есть предназначены для повторного использования кода. Например вам нужно показать один и тот же участок с логиков в разных окнах, тут на помощь как раз и приходят фрагменты. Или что бы в 1 активити не плодить тонну заменяемых объектов, которые могут замедлить работу приложения. Но фрагменты никак не панацея. Нужно уметь разделять понятие фрагментов и активити. Активити это окно грубо говоря, а фрагмент — это фрагмент этого окна.

Мне данный момент в ios нравится, там на подобии фрагментов есть ContainerView, который используют в главном окне что бы разделить какую то логику в окнах. Но там это реализовано так, что разработчик не хочет использовать это повсеместно, а лишь использует при необходимости и только там где это реально нужно

Увы такая мода если новое что то выходит это используют повсеместно, потом начинают осознавать что это не есть хорошо
Объект рейтинга я создаю только один раз. Лагов ни каких нету. Просто анимация создания активити очень некрасива. Я от неё избавился через фрагменты.
Изменили бы ее, хотя бы так для начала)
....
startActivity(intent); //стартуем активити
overridePendingTransition(R.anim.fadein, R.anim.fadeout); //меняем анимацию запуска/закрытия активити
Проверил ваше решение и нашёл только единственный минус — при каждой транзакции нужно вызывать:
overridePendingTransition(R.anim.animation,R.anim.animation);
Файл R.anim.animation пустой, чтобы не было никакой анимации.Мне нравиться ваш способ решения проблемы.
Вообще это общепринятый способ решения, который описан в документации
По поводу 4 проблемы. Я использую конструкцию
if(currentFragment.getClass().equals(FragmentName.class){...}
Я в разработке только недавно, может эта конструкция и не есть правильной, но работает)
Спасибо за ваш комментарий.Мне нравиться ваш способ и в дальнейшем буду его использовать
Так вы же вроде описали что делали сравнение класса и этот метод ведет себя не адекватно
Я использовал ключевое слово instanceof, а не сравнение классов.
Явно что-то делается не так, раз в простом приложении активити тормозит на старте так, что это видно. Фрагменты использовать можно и нужно, но лепить все приложение в одной активити — явно другая крайность. Опять же, если хотите, чтобы у каждого фрагмента был свой идентификатор в стэке — используйте тэги (в качестве тэгов можно использовать статические переменные с понятным названием в каждом фрагменте: addToBackStack(YOUR_FRAGMENT_TAG))

N2. Запихивать все подряд в shared prefernces — не самая лучшая идея. Тяжело с SQLite, структура данных простая и объемы данных небольшие, либо нет большого количества связей таблиц? — попробуйте realm.

N5. По поводу кнопок — кнопки можно создавать и в XML и программно и как вашей душе угодно, а есть еще такая замечательная вещь как data binding… Если надо действительно менять фрагмент в той же активити по кнопке — реализуйте callback в активити. Если это принципиально новое нечто — создавайте интент под новое активити.

N6. Про картинки — если речь идет о добавлении как VectorDrawable, то можно используя third party конвертеры перевести все ваши SVG в XML и потом скопировать при закрытой AS в нужную папку (res\drawable).

Сам весьма «молодой» в мобильной разработке. Из личного опыта могу посоветовать послушать последние google IO, все, что касается технических выступлений + codelabs. Разобраться с архитектурой приложений — MVC и MVVM, и как они могут быть реализованы. Идеальное активити — пустое активити, выносите логику отдельные классы — это поможет и с тестированием и с масштабированием в дальнейшем. Ну и крайне рекомендую разобраться со всеми средствами профилирования и анализа производительности — посмотрите видео из серии performance patterns на официальном канале Google Developers в youtube, пройдите курс от гугла на Udacity — многое откроется по проблеме N3. Курсы из Nano degree на Udacity вообще очень неплохи для начинающих — они записаны самими гугловцами и доступны бесплатно, если вам не нужна красивая бумажка об окончании ND. Удачи!
попробуйте realm.

Если данные типа настроек, или сохранение состояния какой либо переменной, то тут лучше использовать SharedPreferences. Реалм очень большой, если для проекта 6-7 мб лишних не проблема то реалм идеальный вариант, если проект весит меньши библиотеки то реалм зло. Я в своем проекте из-за этого использовал Sugar ORM, она не такая шустрая, но если правильно распределить потоки, то особо не заметно, но принцип работы и синтаксис аналогичен реалму, и вес прибавляется всего пара сотен килобайт. Просто пользователи ругались на размер, а у конкурентов был размер на много ниже, из-за этого пришлось попрощаться с реалмом, и визуально в скорости не проиграл
Тяжело с SQLite...

ORM же для этого придумали. Практически любая библиотека дает примерно такое же удобство в использовании, а разница в скорости для большинства проектов будет не существенна.

N5. По поводу кнопок — кнопки можно создавать и в XML и программно и как вашей душе угодно, а есть еще такая замечательная вещь как data binding…

Воу, это же мрак, особенно для новичка. Сколько не общался с людьми, все только и плюются от этой «фичи».
Лучше уж рассказать про тот же Butter Knife, который делает примерно тоже самое. Но в разы удобнее и понятнее.
Не так страшен databinding (далее db) как его малюют, если никакую логику в XML не городить. Создать на каждый стандартный для вашего приложения кусок UI по вью и по модели, привязанной через db. Далее в xml фрагмента (или активити) как в конструкторе накидываем созданные вью и фрагмент байндим на ViewLogic класс. В классе фрагмента (или активити) только инициализируем наш VL класс (еще лучше — инжектим Dagger-ом). А во VL выполняем всю логику и настраиваем/меняем модели наших «кусков» как душе угодно. При разработке достаточно большого приложения получаем весьма удобный инструментарий, легко масштабируемый и очень легко покрываемый юнит тестами. (P.S. ButterKnife хорош, его использовали до того, как перешли на db)
Ну, к MVVM душа лежит не у всех)
Все равно выглядит слишком сложно, а все ради чего, чтобы уйти от findbyid, onclicklistener`or да нескольких кастомных атрибутов? Ну не знаю. Реально интересная вещь, это слежение за данными и автоматическое изменение состояния view, но опять же, без данной библиотеки это просто еще 1 строчка в коде. Про KISS тоже забывать не нужно)

p.s. Хотя честно говоря, мое знакомство с databinding было уже довольно давно, может они там чего нового придумали, но я увы не в курсе. А все выше сказанное, так, мысли в слух, не более.
Для проблемы 6 можно легко нагуглить решение SVG to XML (SVG2andrid) вот например можно сразу несколько файлов обрабатывать.
Спасибо за ваш комментарий. Вы облегчили мне жизнь раз в 20.
Проблема 5:

если оба фрагмента принадлежат одной активити, то создаёте в этой активити такой метод:

    public void startFragment(Fragment fragment, boolean addToBackStack) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.replace(R.id.container, fragment);

        if(addToBackStack) {
            fragmentTransaction.addToBackStack("frame");
        }
        else {
            fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        }

        fragmentTransaction.commit();
    }


потом во фрагменте А создаёте поле вашей активити:

MainActivity activity;


в методе onCreateView фрагмента А инициализируете её:

activity = (MainActivity) getActivity();


а в конце в обработчике нажатия кнопки во фрагменте А:

        buttonToFragmentB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentB fragment = new FragmentB();
                activity.startFragment(fragment, true);
            }
        });


вуа, как говорится, ля. Бонусом параметром boolean addToBackStack определяете возможность возврата из фрагмента Б во фрагмент А по нажатию кнопки «Back».
Для проблемы 6 используйте поддержку VectorDrawable в студии — это генерация картинок в билдтайм для старых андроидов и использование svg практически напрямую для api >=21. https://android-developers.googleblog.com/2016/02/android-support-library-232.html
Спасибо за ваш комментарий, разобрался.
Sign up to leave a comment.

Articles

Change theme settings