All posts by sniper

Android maintain Fragment State

In this post I would like to focus on one unclear issue during the Android development.

Every body who has worked with Fragment object in Android and he spend at least 1-2 hours to understand how those objects work, he will know that onCreateView() of the Fragment object is called when the fragment is showing for the first time and also when the fragment is resume when user press back button and return to it from previous screen (does not matter Activity or Fragment).

So this point is a little bit sensitive and if you want to have good performance in your app you have to manage it very well. There have 3 base opinions about,  which way is the right way. I will put here them and at the end I will leave my comment about this issue.

  1. Use onSaveInstanceState() in Fragment object to handle the fragment state.
  2. Create instance inside your Fragment of the rootview and keep it until this Fragment is live;
  3. Leave Fragment object to recreate its views by it self every time when it is created/returned from the activity back stack in onCreateView() method;

Well I think the the most right way is the 3-th one and I am applying it in all my fragments.

The second decision is also fine and easy but it have one big problem, when you have to use more then 2-3 instances of your fragments this will consume a lot of memory and the GC will not release this unnecessary objects. Look at this code:

public class SomeFragment extends Fragment {
    View rootView;
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (rootView == null) {
            rootView = inflater.inflate(R.layout.fragment_a, container, false);
            // Setup subviews
        } else {
            // Do not inflate the layout again.
            // The returned View of onCreateView will be added into the fragment.
            // However it is not allowed to be added twice even if the parent is same.
            // So we must remove _rootView from the existing parent view group
            // (it will be added back).
            ((ViewGroup)rootView.getParent()).removeView(rootView);
        }
        return rootView;
    }
}

It seems that you will create only ones your views (inflate) and after that you will miss that part, easy but it will cost problems with the memory for future. You can use this method only if your app has 2-3 screens in one Activity and it doesn’t need more memory and more screens, but if you need then DON’T DO IT.

And the end of this talk I will finally say my solution about the issue:

Leave your Fragment to recreate it’s views  every time when it create it self for the first time or return from the activity back stack. Keep references to your data (Lists) or save them state on the Fragment  onSaveInstanceState() and after that reuse only the data.

Note: Every time when you recreate your views you need to load all fragment data to the new views (they will have new references in the memory, they will be totally new objects), because for example if you have Adapter attached to the RecyclerView, and you recreate your recycler view, the new recycler view need to be associated with this old adapter object. You don’t need to recreate your data list and attached to the adapter ,it is already  there. You just need to tell to the news recyclerview that it’s adapter is the old adapter, otherwise you will see empty recyclerview object without any dat in it.

I hope this explanation  will be useful to somebody and the issue will be clear for all of us.

Android Development – Good Quick Tips

You can download file with more description : – > ANDROID_USEFUL_TIPS

 

Android SDK

Place your Android SDK somewhere in your home directory or some other application-independent location. Some IDEs include the SDK when installed, and may place it under the same directory as the IDE. This can be bad when you need to upgrade (or reinstall) the IDE, or when changing IDEs. Also avoid putting the SDK in another system-level directory that might need sudo permissions, if your IDE is running under your user and not under root.

Project structure

There are two popular options: the old Ant & Eclipse ADT project structure, and the new Gradle & Android Studio project structure. You should choose the new project structure. If your project uses the old structure, consider it legacy and start porting it to the new structure.
Old structure:
old-structure
├─ assets
├─ libs
├─ res
├─ src
│ └─ com/futurice/project
├─ AndroidManifest.xml
├─ build.gradle
├─ project.properties
└─ proguard-rules.pro
New structure:
new-structure
├─ library-foobar
├─ app
│ ├─ libs
│ ├─ src
│ │ ├─ androidTest
│ │ │ └─ java
│ │ │ └─ com/futurice/project
│ │ └─ main
│ │ ├─ java
│ │ │ └─ com/futurice/project
│ │ ├─ res
│ │ └─ AndroidManifest.xml
│ ├─ build.gradle
│ └─ proguard-rules.pro
├─ build.gradle
└─ settings.gradle
The main difference is that the new structure explicitly separates ‘source sets’ (main, androidTest), a concept from Gradle. You could, for instance, add source sets ‘paid’ and ‘free’ into src which will have source code for the paid and free flavours of your app.
Having a top-level app is useful to distinguish your app from other library projects (e.g., library-foobar) that will be referenced in your app. The settings.gradle then keeps references to these library projects, which app/build.gradlecan reference to.

There are short list with useful tips:

      Use Gradle and its recommended project structure

 

      Put passwords and sensitive data in gradle.properties

 

      Use the Jackson library to parse JSON data

 

      Don’t write your own HTTP client, use Volley or OkHttp libraries

 

      Avoid Guava and use only a few libraries due to the 65k method limit

 

      Use Fragments to represent a UI screen

 

      Use Activities just to manage Fragments

 

      Layout XMLs are code, organize them well

 

      Use styles to avoid duplicate attributes in layout XMLs

 

      Use multiple style files to avoid a single huge one

 

      Keep your colors.xml short and DRY, just define the palette

 

      Also keep dimens.xml DRY, define generic constants

 

      Do not make a deep hierarchy of ViewGroups

 

      Avoid client-side processing for WebViews, and beware of leaks

 

      Use Robolectric for unit tests, Robotium for connected (UI) tests

 

      Use Genymotion as your emulator

 

      Always use ProGuard or DexGuard

 

      Use SharedPreferences for simple persistence, otherwise ContentProviders

 

    Use Stetho to debug your application

Android Circular Progress Bar

Just and example how to create circular progress bar in Android. It works on API < 21 and API > 21.
The default value for useLevel has changed over the Android versions and in API > 21 it is false, This make problems for progress bars when you want to be circular and your bar will be always 100% full. Here is a piece on investigation related to it.


And for your progress bar you can use following example:

> ,)^jwk'Z ,ҷ)^ΉjVv"vVpaMݮ^mMݮ ,i^vi^ˬ{Zݮ ,Fv"vfM؝' ,ڝZʋܜz{^

Here is some more explanations about that.
Given that, it seems that:

useLevel is defaulted to true in Android < 5.0, causing the background ring to follow the progress value if useLevel is not set in its ring shape, thus making it hidden behind the progress indicator ring. useLevel is defaulted to false in Android >= 5.0, causing the progress indicator ring to be fully painted if useLevel is not set in its ring shape.

How to simulate Download Progress

Hi there I just want to share how can simulate in Android download progress.
With this code you can test your Progress Bars for proper work.
We have to methods startProgress with the view that we want to update for progress usually this is Progress Bar, and second method is holdForSimulation()
public void startProgress(final DownloadButton button) {
// do something long
Runnable runnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i <= 10; i++) {
final int value = i;
holdForSimulation();
button.post(new Runnable() {
@Override
public void run() {
button.setProgress(value);
}
});
}
}
};
new Thread(runnable).start();
}
// Simulating download
private void holdForSimulation() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Just past your view to startProgress and wait for update.

Android get current language

Here are the different ways to get current language in Android application, depend of the case you like to use.

Locale.getDefault().getLanguage() —> en
Locale.getDefault().getISO3Language() —> eng
Locale.getDefault().getCountry() —> US
Locale.getDefault().getISO3Country() —> USA
Locale.getDefault().getDisplayCountry() —> United States
Locale.getDefault().getDisplayName() —> English (United States)
Locale.getDefault().toString() —> en_US

It is useful when you want to change your application language, you can check which language is the current one.

Android Screen Sizes

The Table bellow represent a lot of Android Devices Screen sizes:

————————— —– ———— ————— ——- ———– —————- — ———-
Device, Inches ResolutionPX, Density, DPI, ResolutionDP, AspectRatios, SysNavYorN, ContentResolutionDP
————————— —– ———— ————— ——- ———– —————- — ———-
Galaxy Y, 320 x 240, ldpi 0.75, 120, 427 x 320, 4:3, 1.3333, 427 x 320
? 400 x 240 ldpi 0.75 120 533 x 320 5:3 1.6667 533 x 320
? 432 x 240 ldpi 0.75 120 576 x 320 9:5 1.8000 576 x 320
Galaxy Ace 480 x 320 mdpi 1 160 480 x 320 3:2 1.5000 480 x 320
Nexus S 800 x 480 hdpi 1.5 240 533 x 320 5:3 1.6667 533 x 320
“Galaxy SIII Mini” 800 x 480 hdpi 1.5 240 533 x 320 5:3 1.6667 533 x 320
? 854 x 480 hdpi 1.5 240 569 x 320 427:240 1.7792 569 x 320

Galaxy SIII 1280 x 720 xhdpi 2 320 640 x 360 16:9 1.7778 640 x 360
Galaxy Nexus 1280 x 720 xhdpi 2 320 640 x 360 16:9 1.7778 640 x 360
HTC One X 4.7″ 1280 x 720 xhdpi 2 320 640 x 360 16:9 1.7778 640 x 360
Nexus 5 5″ 1920 x 1080 xxhdpi 3 480 640 x 360 16:9 1.7778 YES 592 x 360
Galaxy S4 5″ 1920 x 1080 xxhdpi 3 480 640 x 360 16:9 1.7778 640 x 360
HTC One 5″ 1920 x 1080 xxhdpi 3 480 640 x 360 16:9 1.7778 640 x 360
Galaxy Note III 5.7″ 1920 x 1080 xxhdpi 3 480 640 x 360 16:9 1.7778 640 x 360
HTC One Max 5.9″ 1920 x 1080 xxhdpi 3 480 640 x 360 16:9 1.7778 640 x 360
Galaxy Note II 5.6″ 1280 x 720 xhdpi 2 320 640 x 360 16:9 1.7778 640 x 360
Nexus 4 4.4″ 1200 x 768 xhdpi 2 320 600 x 384 25:16 1.5625 YES 552 x 384
————————— —– ———— ————— ——- ———– —————- — ———-
Device, Inches ResolutionPX, Density, DPI, ResolutionDP, AspectRatios, SysNavYorN, ContentResolutionDP
————————— —– ———— ————— ——- ———– —————- — ———-
? 800 x 480 mdpi 1 160 800 x 480 5:3 1.6667 800 x 480
? 854 x 480 mdpi 1 160 854 x 480 427:240 1.7792 854 x 480
Galaxy Mega 6.3″ 1280 x 720 hdpi 1.5 240 853 x 480 16:9 1.7778 853 x 480
Kindle Fire HD 7″ 1280 x 800 hdpi 1.5 240 853 x 533 8:5 1.6000 853 x 533
Galaxy Mega 5.8″ 960 x 540 tvdpi 1.33333 213.333 720 x 405 16:9 1.7778 720 x 405
Sony Xperia Z Ultra 6.4″ 1920 x 1080 xhdpi 2 320 960 x 540 16:9 1.7778 960 x 540

Kindle Fire (1st & 2nd gen) 7″ 1024 x 600 mdpi 1 160 1024 x 600 128:75 1.7067 1024 x 600
Tesco Hudl 7″ 1400 x 900 hdpi 1.5 240 933 x 600 14:9 1.5556 933 x 600
Nexus 7 (1st gen/2012) 7″ 1280 x 800 tvdpi 1.33333 213.333 960 x 600 8:5 1.6000 YES 912 x 600
Nexus 7 (2nd gen/2013) 7″ 1824 x 1200 xhdpi 2 320 912 x 600 38:25 1.5200 YES 864 x 600
Kindle Fire HDX 7″ 1920 x 1200 xhdpi 2 320 960 x 600 8:5 1.6000 960 x 600
? 800 x 480 ldpi 0.75 120 1067 x 640 5:3 1.6667 1067 x 640
? 854 x 480 ldpi 0.75 120 1139 x 640 427:240 1.7792 1139 x 640

Kindle Fire HD 8.9″ 1920 x 1200 hdpi 1.5 240 1280 x 800 8:5 1.6000 1280 x 800
Kindle Fire HDX 8.9″ 2560 x 1600 xhdpi 2 320 1280 x 800 8:5 1.6000 1280 x 800
Galaxy Tab 2 10″ 1280 x 800 mdpi 1 160 1280 x 800 8:5 1.6000 1280 x 800
Galaxy Tab 3 10″ 1280 x 800 mdpi 1 160 1280 x 800 8:5 1.6000 1280 x 800
ASUS Transformer 10″ 1280 x 800 mdpi 1 160 1280 x 800 8:5 1.6000 1280 x 800
ASUS Transformer 2 10″ 1920 x 1200 hdpi 1.5 240 1280 x 800 8:5 1.6000 1280 x 800
Nexus 10 10″ 2560 x 1600 xhdpi 2 320 1280 x 800 8:5 1.6000 1280 x 800
Galaxy Note 10.1 10″ 2560 x 1600 xhdpi 2 320 1280 x 800 8:5 1.6000 1280 x 800
————————— —– ———— ————— ——- ———– —————- — ———-
Device, Inches ResolutionPX, Density, DPI, ResolutionDP, AspectRatios, SysNavYorN, ContentResolutionDP
————————— —– ———— ————— ——- —

Sorry about the bad format!!!
In additional to the data above, here is some more information:

A set of six generalized densities:
ldpi (low) ~120dpi
mdpi (medium) ~160dpi
hdpi (high) ~240dpi
xhdpi (extra-high) ~320dpi
xxhdpi (extra-extra-high) ~480dpi
xxxhdpi (extra-extra-extra-high) ~640dpi

The ldpi, mdpi and hdpi refer to screen density, which means how much pixels can fit into a single inch.

the ratio in pixels between them is:

ldpi = 1:0.75
mdpi = 1:1
hdpi = 1:1.5
xhdpi = 1:2
xxhdpi = 1:3
xxxhdpi = 1:4
so lets take an image with about the size of 100X100:

for mdpi it should be 100X100
for ldpi it should be 75X75
for hdpi it should be 150X150
for xhdpi it should be 200X200
for xxhdpi it should be 300X300
for xxxhdpi it should be 400X400

this way, for screens with the same size but different DPI, all the images seem the same size on screen.

Also you have multiple screen size types small, normal, large, xlarge and each one of them can be ldpi, mdpi, hdpi, xhdpi, xxhdpi (Nexus 10) or xxxhdpi.

You can try to create a splash screen image that fit to each and every screen type which gives you 4*5 = 20 different images.