Android - Това изтичане на памет ли е? (Позоваване на обект, създаден в дейност в друга дейност като статична променлива)

Да кажем, че имам Activity1, която създава прост потребителски обект CustObject. CustObject не препраща към никакъв контекст или подобен тип обект. След това искам да предам този екземпляр на Activity2, като го задам като статична променлива в Activity2. Разгледайте съответния код:

public class CustObject {

    private int attr;

    public CustObject(int arg) { // takes only integers and Strings
        attr = arg;
    }
}

Ето първата дейност:

public class Activity1 extends Activity {

    private CustObject co;

    @Override
    protected void onCreate(Bundle b) {
        co = new CustObject(42);
    }

    public void launchActivity2() {
        Activity2.co = co;
        startActivity(new Intent(this, Activity2.class);
    }
}

И ето втората дейност:

public class Activity2 extends Activity {

    public static CustObject co;

    @Override
    protected void onCreate(Bundle b) {
        // stuff
    }

    // Do operations on the co object.
}

Така че моята мисъл е, че когато стартираме Activity2, ние само „изтичаме“ на съобекта - който е търсен - но останалата част от Activity1 и неговия контекст могат да бъдат събрани боклук, ако е необходимо, без никакви проблеми/течове, нали?

Имайте предвид, че искам да го направя по този начин, защото CustObject co вероятно ще бъде променен от Activity2 и бих искал тези промени да се показват автоматично в Activity1, ако не е бил убит. Ако е бил убит, тогава работи, защото всичко ще бъде презаредено и промените в CustObject в Activity2 също са съхранени в база данни.

Благодаря ти за помощта!

PS: Също така, винаги съм се чудил дали стартирането на дейност чрез даване на „това“ като контекст за намерение е изтичане на родителската дейност??


person Louis Durand    schedule 04.08.2016    source източник
comment
Най-общо казано, статичните променливи не са начинът, по който споделяте данни между дейности. Activity1 може да бъде убит във всеки един момент от операционната система за управление на паметта   -  person OneCricketeer    schedule 04.08.2016
comment
Ще обичате смъртта на процеса, когато Android убие приложението ви, вие се връщате някъде по средата, но всичките ви статични полета са изчистени! :)   -  person EpicPandaForce    schedule 04.08.2016
comment
Заедно с тази точка - вашите дейности се наслагват една върху друга, така че наистина ли се нуждаете от промени, които да бъдат изобразени автоматично на екран, който не можете да видите? Можете да предавате данни между Intents от startActivityForResult и след това setResult, последвано от onActivityResult   -  person OneCricketeer    schedule 04.08.2016
comment
Ако Activity1 бъде убит, CustObject co също ще бъде изчистен? Но ако имам препратка към него в Activity2, не трябва ли да се изчиства?   -  person Louis Durand    schedule 04.08.2016
comment
@LouisDurand, след като бъде зададен статичен, обектът няма да бъде GCed, независимо от състоянието на Дейности.   -  person Vaiden    schedule 04.08.2016
comment
@Vaiden, да, това е законно за мен. Но само CustObject, а не контекста на Activity1.   -  person Louis Durand    schedule 04.08.2016
comment
@EpicPandaForce да, всъщност мисля, че има проблем с моето решение, ако Activity2 get бъде убит и след това възобновен.. Така че ще отида с Intents и startActivityForResult и така нататък.. Просто е малко повече работа и по-малко удобно x)   -  person Louis Durand    schedule 04.08.2016
comment
Смъртта на процеса настъпва при състояние на ниска памет. Това означава, че вашият стек от дейности се възстановява от записите на стека от дейности и екземплярът на приложението също се създава отново. Всички статични полета се изчистват, освен ако не ги запазите ръчно в пакет и обратно. Може би си мислите, че състоянието на ниска памет е рядкост, но просто стартирайте Pokemon Go и Chrome и те някак си се убиват един друг всеки път (и всяко друго работещо приложение) :P   -  person EpicPandaForce    schedule 04.08.2016
comment
@EpicPandaForce да, знам, всъщност имам смартфон с доста ниски спецификации, което е добре като разработчик, тъй като вече съм срещал подобен проблем ^^ Въпросът е какъв вид обект мога да вмъкна в Bundle/Intent ? Мисля, че трябва да може да се сериализира... Е, ще проуча всичко това.   -  person Louis Durand    schedule 04.08.2016
comment
Сериализирано или парцелируемо.   -  person EpicPandaForce    schedule 04.08.2016
comment
Използването на this като параметър Context при създаване на Intent не причинява изтичане на памет. Context се използва само за извличане на името на пакета на Component за стартиране. Не се съхранява в Intent.   -  person David Wasser    schedule 05.08.2016
comment
@DavidWasser о, добре изглежда законно тогава. Но защо има значение дали подаваме приложение или дейност, ако става дума само за извличане на името на пакета? Благодаря все пак.   -  person Louis Durand    schedule 06.08.2016
comment
В случая няма значение. Както казах, можете да използвате всеки Context, който искате в конструктора Intent с 2 аргумента. Няма абсолютно никаква разлика.   -  person David Wasser    schedule 06.08.2016
comment
@DavidWasser Достатъчно смешно, видях куп статии/публикации за неща, свързани с обхвата и че дейностите ТРЯБВА да се използват за стартиране на друга дейност върху тях. И сега ми казваш, че е абсолютно същото??   -  person Louis Durand    schedule 07.08.2016
comment
Не вярвайте на всичко, което четете. Изходният код за Android е достъпен за разглеждане на grepcode.com. Потърсете себе си. Или просто помислете: нямате нужда от Context, за да започнете друго Activity с Intent. Можете да създадете Intent с помощта на конструктора с един аргумент, който просто задава ДЕЙСТВИЕТО.   -  person David Wasser    schedule 07.08.2016


Отговори (1)


So...

  1. Статичните променливи се намират в областта perm-gen. На обикновен английски - всички те се съхраняват в определена зона в купчината. Повече тук: статично разпределение в java - heap, стек и постоянно генериране

  2. Така че вашият Activity2.co обект няма да бъде събиран за боклук, независимо от състоянието на Activity1 или Activity2. Това не е точно "изтичане", но веднъж зададен - обектът ще заема паметта за времето на живота на процеса.

  3. Android може по всяко време да "убие" Activity, за да освободи памет. Предполага се, че Activitys поддържат състоянието си чрез savedState обект. Повече тук: https://developer.android.com/training/basics/activity-lifecycle/recreating.html

  4. Така че съхраняването на статични обекти може да не е правилният начин за предаване на данни между Activitys. Ето дискусия за алтернативите: Как да предавам данни между Дейности в приложението за Android?

person Vaiden    schedule 04.08.2016