13 Şubat 2018 Salı

Android Dersleri 14 - Launchmode of an activity, onNewIntent() , call an activity with an intent


14-Launchmode of an activity, onNewIntent() , call an activity with an intent

There are 4 types of launchMode available :
        - standard
        - singleTop
        - singleTask
        - singleInstance
        OnNewIntent() always gets called for singleTop/Task activities except for the first time when activity is created. At that time onCreate is called. ( launchMode'u singleTop ve singleTask olan activity'ler ilk defa yaratıldıklarında onCreate() method'u çağırılır. Bu activity'ler tekrar ekrana getirilecekleri zaman ise onNewIntent() method'u çağırılır otomatik olarak. )
        If you set to singletop, the activity will not be launched if it is already running at the top of the history stack. It will not relaunch just show from stack. ( LaunchMode'u singletop olan bir Activity, eğer history stack'ın tepesinde çalışmaktaysa, bu activity tekrar başlatılmaz(tekrar launch edilmez), history stack'dan çıkarılıp gösterilir. Yani çalışmakta olan activity'nin launchmode'u singleTop ise, bu activity'yi tekrar çağırırsak activity'nin sırayla şu method'ları çağırılır :
- onPause()
- onNewIntent()
- onResume()
Yeni bir singleTop activity yaratılmaz yani onCreate() method'u çağırılmaz.
        Eğer history stack'ın en üstünde çalışmakta olan activity singleTop launchmode'unda değilse ve singleTop launchmode'unda bir activity çalıştırmak istersek  singleTop launchmode'undaki activity'nin sırayla şu method'ları çağırılır :
- onCreate()
- onStart(),
- onResume()  )
@Override
public void onCreate(Bundle savedState)
{
        super.onCreate(savedState);
        onNewIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent)
{
  super.onNewIntent(intent);
  //code
}

        onNewIntent() is meant as entry point for singleTop activities which already run somewhere else in the stack and therefore can't call onCreate().  ( Stack'ın en üstünde çalışmakta olan bir singleTop activity varsa, singleTop activity'nin tekrar yaratılmasına gerek yoktur, dolayısıyla bu activity tekrar çağırılırsa onCreate() method'u çağırılmaz, sırayla onPause(),onNewIntent(),onResume() method'ları çağırılır.  )
        For example most of the time my onNewIntent() methods simply looks like this: ( Stackoverflow'daki bir arkadaş, genellikle onNewIntent() method'unu aşağıdaki gibi implement ediyormuş, setIntent() method'unu çağırıyormuş, onResume() method'unda ise getIntent() method'unu çağırıyormuş. Yani sırayla onPause(),onNewIntent(), onResume() çağırılacağı için onNewIntent()'de intent object'i set ediyor, onResume()'de intent object'i getiriyor.  )
@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    // getIntent() should always return the most recent
    setIntent(intent);
}
With all setup logic happening in onResume() by utilizing getIntent().

--------- http://www.helloandroid.com/tutorials/communicating-between-running-activities
        First of all by default if you call an activity with an intent, a new instance of that activity will be created and displayed, even if another instance is already running. To avoid this the activity must be flagged that, it should not be instantiated multiple times. To achieve this we will set the launchMode of the activity to singleTask in the AndroidManifest.xml. ( Bir activity'yi intent ile çağırınca, default olarak yeni bir activity yaratılır, çünkü activity'nin default launchmode'u standard'dır. Bunu önlemek için, launchmode'u bu örnekte singleTask yapalım, bu sayede artık bu activity birden fazla defa yaratılmayacaktır, sadece bir defa yaratılacaktır, ancak dikkat edelim singleTask activity'ye intent gönderildiğinde activity stack'da başka activity'ler varsa bunlar yok edilir   )
1.   <activity android:name="Activity1" android:launchMode="singleTask" android:label="@string/app_name">
        When we call singleTask activity using an intent, if there is an existing instance of the singleTask activity, the system will call the onPause(), onNewIntent(), onResume() methods of the activity respectively. However, onCreate() method will not run this time. ( Intent ile bir singleTask activity'yi çağırdığımızda, singleTask activity zaten varsa, singleTask activity'nin onPause(), onNewIntent(), onResume() method'ları çağırılır sırayla. Ancak onCreate() çağırılmaz. )
        Intent ile bir singleTask activity'yi çağırdığımızda, singleTask activity yoksa, yeni bir task yaratılır, task'ın boş activity stack'ına singleTask activity koyulur.

Call an activity with an intent

      What does "call an activity with an intent" mean? Here is the answer! In the below sendMessage() method, an Intent object is created then startActivity(intent) method is called. This is an example of callin an activity named DisplayMessageActivity with an intent.
public class MainActivity extends AppCompatActivity {

    public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

    }



    /** Called when the user clicks the Send button */

    public void sendMessage(View view) {

        Intent intent = new Intent(this, DisplayMessageActivity.class);

        EditText editText = (EditText) findViewById(R.id.edit_message);

        String message = editText.getText().toString();

        intent.putExtra(EXTRA_MESSAGE, message);

        startActivity(intent);

    }

}

When is onNewIntent() method called?

onNewIntent() method'u şu durumlarda çalışır.
- Activity stack'ın en üstünde singleTop activity varken, intent ile singleTop activity çağırırsak, singleTop activity'nin onCreate() method'u çağırılmaz, sırayla onPause(), onNewIntent(), onResume() method'ları çağırılır.
- Sistemde varolan bir singleTask activity varsa, intent ile singleTask activity çağırırsak, singleTask activity'nin onCreate() method'u çağırılmaz, sırayla onPause(), onNewIntent(), onResume() method'ları çağırılır.
- Sistemde varolan bir singleInstance activity varsa, intent ile singleInstance activity çağırırsak, singleInstance activity'nin onCreate() method'u çağırılmaz, sırayla onPause(), onNewIntent(), onResume() method'ları çağırılır.
İlk kez bir activity yaratılırken, onCreate() method'u çağırılır, onNewIntent() method'u çağırılmaz, yani bu 2 method'un birbirine zıt olduğunu ve birisi çağırıldığında diğerinin çağırılmadığını düşün. Bu 2 method birbirine zıttır.

        You can invoke onNewIntent always by putting it into onCreate method like(onNewIntent method'unun her durumda çağırılıyor olmasını istiyorsak, onCreate() method'unun içerisinde onNewIntent() method'unu çağırmalıyız.)
@Override
public void onCreate(Bundle savedState)
{
    super.onCreate(savedState);
    onNewIntent(getIntent());
}
 
@Override
protected void onNewIntent(Intent intent) 
{
  super.onNewIntent(intent);
  //code
}

        OnNewIntent() always get called for singleTop/singleTask/singleInstance activities except for the first time when activity is created. At that time onCreate is called. ( Activity ilk defa yaratılıyorsa onCreate() method'u çağırılır, otherwise onNewIntent() method'u çağırılır. )
-------- https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en
        Basically we could assign a launchMode directly as an attribute of <activity> tag inside AndroidManifest.xml file list this:
<activity
    android:name=".SingleTaskActivity"
    android:label="singleTask launchMode"
    android:launchMode="singleTask">

standard

This is the default launch mode.
The behavior of Activity set to this mode is a new Activity will always be created to work separately with each Intent sent. Imagine, if there are 10 Intents sent to compose an email, there should be 10 Activities launch to serve each Intent separately. As a result, there could be an unlimited number of this kind of Activity launched in a device. ( Activity'ye her intent gönderildiğinde yeni bir Activity yaratılacaktır.  )

singleTop

        The next mode is singleTop. It acts almost the same as standard one which means that singleTop Activity instance could be created as many as we want. Only difference is if there already is an Activity instance with the same type at the top of stack in the caller Task, there would not be any new Activity created, instead an Intent will be sent to an existed Activity instance through onNewIntent() method. ( singleTop activity'den aynı task(aynı uygulama) içerisinde birden fazla yaratılabilir, bu özelliği standard activity'ye benzer. Standard activity'den farkı ise şudur: stack'ın tepesinde singleTop bir activity varsa, yeni bir activity yaratılmaz, bunun yerine varolan activity instance'a onNewIntent() method'uyla bir intent gönderilir.   )
        In singleTop mode, you have to handle an incoming Intent in both onCreate() and onNewIntent() to make it works for all the cases. ( singleTop mod'daki bir activity'nin tüm muhtemel case'ler için düzgün çalışmasını istiyorsak, gelen bir intent'i hem onCreate() hem de onNewIntent() method'larında handle etmeliyiz. )
        A sample use case of this mode is a Search function. Let's think about creating a search box which will lead you to a SearchActivity to see the search result. For better UX, normally we always put a search box in the search result page as well to enable user to do another search without pressing back. (SingleTop launchmode'unun örnek bir kullanım amacı, Search fonksiyonudur. Ekrana bir search box ve buton koyduğumuzu düşünelim. Kullanıcı bir arama yaptığında SearchActivity gösterilsin. Ve her arama sonucunda kullanıcıya search box ve butonu tekrar gösterelim ki kullanıcının geri tuşuna basmasına gerek kalmadan başka bir arama yapabilmesini sağlayalım.)
        Now imagine, if we always launch a new SearchActivity to serve new search result, 10 new Activities for 10 searching. It would be extremely weird when you press back since you have to press back for 10 times to pass through those search result Activities to get back to your root Activity. ( Eğer standard launchmode kullanırsak ve kullanıcı art arda 10 arama yaparsa, 10 tane yeni search activity yaratılır. Geri gelmeye çalıştığımızda history stack'da 10 tane search result activity olduğu için, 10 defa geri gelmemiz gerekir search result activity'lerden önceki sayfaya geri gelmek için. Bu da çok tuhaf ve salakça olur. )
        Instead, if there is SearchActivity on top of stack, we better send an Intent to an existed Activity instance and let it update the search result. Now there will be only one SearchActivity placed on top of stack and you can simply press just back button for a single time to get back to previous Activity. Makes a lot more sense now. ( Bahsettiğimiz Search fonksiyonu için yapmamız gereken şey şudur: Eğer stack'ın tepesinde bir SearchActivity varsa, bu activity'yi yeniden yaratmamalı sadece intent göndermeliyiz, böylece search sonuçlarını güncellemeliyiz, bunun için search activity'nin launchmode'unu singleTop yapmalıyız. Bu durumda, search sonuçlarından bir önceki activity'ye gelmek için geri tuşuna bir defa basmamız yeterli olacaktır. Bu da en mantıklı yoldur. )
        Anyway singleTop works with the same task as caller only. If you expect an Intent to be sent to an existed Activity placed on top of any other Task, I have to disappoint you by saying that it doesn't work that way. In case Intent is sent from another application to an singleTop Activity, a new Activity would be launched in the same aspect as standard launchMode (pre-Lollipop: placed on top of the caller Task, Lollipop: a new Task would be created). ( Şimdiye kadar anlatttığımız singleTop launchMode'unun özelliği, aynı task'daki bir activity'ye intent gönderilirken geçerlidir. Eğer farklı bir task'daki(farklı bir uygulamadaki) bir activity'ye intent gönderiyorsak, singleTop burada anlattığımız şekilde çalışmaz.
        Farklı bir task'dan(farklı bir uygulamadan), bir singleTop activity'ye intent gönderilirse, yeni bir activtiy yaratılır, aynı standard launchMode gibi. )
        This mode is quite different from standard and singleTop. An Activity with singleTask launchMode is allowed to have only one instance in the system (a.k.a. Singleton). ( singleTask activity, standard and singleTop activity'lerden tamamen farklıdır. Sistemde aynı anda sadece bir tane singleTask activity varolabilir, 2 tane olamaz.)
        If there is no singleTask Activity instance existed in the system yet, new one would be created and simply placed on top of stack in the same Task. (Eğer sistemde singleTask activity yoksa, yeni bir singleTask activity yaratılır.)
        But if there is an existed one, all of Activities placed above that singleTask Activity would be automatically and cruelly destroyed in the proper way (lifecycle trigged) to make that an Activity we want to appear on top of stack. In the mean time, an Intent would be sent to the singleTask Activity through the lovely onNewIntent() method. (Eğer sistemde singleTask activity varsa, task'ın activity stack'daki tüm activity'ler silinir sadece singleTask activity silinmez(singleTask activity'nin onPause(),onNewIntent(), onResume() method'ları çağırılır). )
        A sample use case of this mode is any Entry Point Activity for example Email Client's Inbox page or Social Network's Timeline. Those Activities are not designed to have more than one instance so singleTask would do a job perfectly. Anyway you have to use this mode wisely since Activities could be destroyed without user's acknowledgement in this mode like described above.
        This mode is quite close to singleTask, only single instance of Activity could be existed in the system. The difference is Task hold this Activity could have only one Activity, the singleInstance one. If another Activity is called from this kind of Activity, a new Task would be automatically created to place that new Activity. Likewise, if singleInstance Activity is called, new Task would be created to place the Activity.  ( singleTask activity'ye çok benzer. Sistemde aynı anda sadece bir tane singleInstance activity varolabilir, 2 tane olamaz. singleTask activity'den farkı şudur, task'da sadece 1 tane activity vardır o da singleInstance activity'dir. singleTask activity'den başka type'da bir activity çağırılırsa, yeni bir task yaratılıp çağırılan activity bu task'a koyulur. Benzer şekilde başka bir activity'den singleInstance activity çağırılırsa da yeni bir task yaratılır. Ayrıca singleInstance activity'den singleInstance activity çağırılırsa, yeni bir activity yaratılmaz sırayla onPause(),onNewIntent(),onResume() method'ları çağırılır.  )
        This mode is rarely used. Some of the real use case is an Activity for Launcher or the application that you are 100% sure there is only one Activity. Anyway I suggest you not to use this mode unless it is really necessary.

        Aşağıda PlayStore'dan indirdiğim "Activities Launchmode" isimli uygulamayı inceledim.
Yukarıda task'ları görüyoruz. Herbir uygulama içinbir task vardır gibi düşünebiliriz. Aynı task içinde launchpoint'i standard veya singleTop olan bir activity'ye intent gönderdiğimizde aynı task içinde çalışılır, yeni bir task açılmaz. Bu yüzden   standard ve singleTop activity'ler benzerdir, singleTask ve singleInstance activity'ler benzerdir deriz ve bunları 2 ayrı grupta inceleriz.

        Butonlara basarak farklı activity'leri başlatabiliriz. Standard'a tıklayınca, standard bir activity'ye intent gönderdiğimizde yeni bir activity yaratılacağı için başlatılan bu standard activity activity stack'a koyulur.
        SingleTop'a tıklayınca, activity stack'ın tepesinde singleTop activity var mı diye bakar, varsa sırayla onPause(),onNewIntent(), onResume() method'larını çağırır yani yeni bir activity yaratmaz onCreate() method'unu  çağırmaz. Yoksa yeni bir activity yaratır(onCreate() çağırılır) ve activity stack'a koyulur. Yukarıdaki örnekte activity stack'da standard ve singleTop activity'ler vardır, yeşil çizgiler standard activity'dir, mavi çizgiler singleTop activity'dir.
        singleTask'a tıklayınca, sistemde singleTask activity yoksa aşağıdaki sarı ekrandaki gibi yeni bir task yaratılır. Bu task'ın activity stack'ında sadece singleTask activity vardır. standard ve singleTop activity'ye tıklayarak bu  task'ın activity'sine bu activity'leri eklemek mümkündür. Ancak singleTask'a tekrar tıklarsak, bu task'ın activity stack'ını temizler, activity stack'da sadece singleInstance kalır. Eğer singleTask'a tıkladığımızda, sistemde singleTask activity varsa yeni bir activity yaratılmaz(onCreate() çağırılmaz), sırayla onPause(), onNewIntent(), onResume() method'ları çağırılır.
      

        singleInstance'a tıklarsak, yeni bir task yaratır ancak bu task'ın activity stack'ına başka hiçbir activity eklenemez. Aşağıdaki gibi kırmızı ekranlı bir singleInstance activity gösterilir ekranda. Bu ekrandaki standard veya singleTop butonuna tıklarsak, bu activity standard veya singleTop activity ile başlatılmış bir task'da açılır, standard veya singleTop activity ile başlatılmış bir task yoksa yeni bir task yaratılıp activity bu task'da açılır. Son durumda tek bir uygulamamız olmasına rağmen bu uygulama tarafından açılmış 3 farklı task'a sahibiz bunlar aşağıda gösterilmiştir, bu task'lardan ilki sadece standard ve singleTop activity'leri içerir, ikincisi singleTask, standard ve singleTop activity'leri içerir, üçüncüsü sadece singleInstance activity içerir.
        singleTask ve singleInstance activity'ler kullanıcılara tuhaf gelebilir çünkü uygulamalarda genellikle bunlar kullanılmadığı için kullanıcılara yabancı bir durum gibi gelebilir. Bu yüzden mümkünse singleTask ve singleInstance activity kullanma, standard ve singleTop activity kullan!


Hiç yorum yok:

Yorum Gönder