Open In App

App Development for Android in 2017: Challenges and Solutions

Last Updated : 15 Nov, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Since Android OS took over the world, it’s hard to imagine the outsourcing niche without a mobile app development. Usually, the launching of the app is a quite time-consuming process. When a company decides to make an enterprise application, it is needed here and now. That’s why the mechanism of building hybrid or native apps for Android usually requires using a third-party library to speed-up the process. Let’s take a look at the top-four of them, which are often used by mobile application developers nowadays and review their most interesting functions and possibilities.

Butter Knife

Butter Knife is a small library that is used to reduce the number of the code lines in your project and make it clear. The library doesn’t affect the final apk-file size. Butter Knife uses annotations to bind objects from an xml file with objects from application’s logic. Also, it binds some objects’ actions (for example, you click on the object or choose an item from the list) with the overall logic of an application.
If you want to include this library in your project, write in your module’s gradle:




compile 'com.jakewharton:butterknife:8.4.0' annotationProcessor
 'com.jakewharton:butterknife-compiler:8.4.0'


After this action, Butter Knife library will be ready for use. In the example below, you can see how you can make the Button item bound with TextView item, performing a simple activity: when user clicks on the button, the text changes.




@BindView(R.id.text_view)
TextView textView;
@BindView(R.id.button)
Button button;
 
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
}
 
@OnClick(R.id.button)
public void onButtonClick()
{
    textView.setText("On Button Click");
}


As simple as that. You don’t need to use findViewById for each view item and don’t need to implement onClickListener and the respective methods onClick.
You can also bind pre-defined resources with annotation. In our example it will look like:

@BindView(R.id.button)
Button button;
@BindString(R.string.text)
String text;

@OnClick(R.id.button)
public void onButtonClick()
{
textView.setText(text);
}

Now our resource file contains string value text. If we need to add multiple translates for this value – we can duplicate the resource file as many times, as many languages we want to have in the app, and translate the needed information within each file into the foreign language.

You can use ButterKnife.bind anywhere you would otherwise put findViewById calls. It means that you may use it in fragments, view holders, etc.

This is only a tiny piece of what this library can do. If you are interested in the other possibilities of this one, just visit the official Butter Knife web-page and read more.

Glide

Glide is an image-loading and caching library for Android focused on smooth scrolling. If you need to display images, video stills or animated GIFs in your application – this library is for you. In order to include this library in your project, you need to write one row of code in your module’s gradle:




compile 'com.github.bumptech.glide:glide:3.7.0'
 
    // When you need to show an image, type-in this one:
 
    Glide
        .with(this)
        .load("http://goo.gl/gEgYUd")
        .into(imageView);


Where “http://goo.gl/gEgYUd” – our image’s URL, imageView – the window where the image is loaded and showed.
Glide provides not only the function of displaying our images. It can also produce memory caching and a big variety of transformations. The function, which is quite popular due to the fact, that it’s frequently used by mobile application developers – is creating rounded image view. For this solution you need to create a custom class extended BitmapTransformation and override the method transform:




public class CircleTransform extends BitmapTransformation {
    public CircleTransform(Context context)
    {
        super(context);
    }
 
    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform,
                               int outWidth, int outHeight)
    {
        return circleCrop(pool, toTransform);
    }
 
    private static Bitmap circleCrop(BitmapPool pool, Bitmap source)
    {
        if (source == null)
            return null;
 
        int size = Math.min(source.getWidth(), source.getHeight());
        int x = (source.getWidth() - size) / 2;
        int y = (source.getHeight() - size) / 2;
 
        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);
        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);
        if (result == null)
            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
 
        Canvas canvas = new Canvas(result);
        Paint paint = new Paint();
        paint.setShader(new BitmapShader(squared,
                                         BitmapShader.TileMode.CLAMP,
                                         BitmapShader.TileMode.CLAMP));
        paint.setAntiAlias(true);
        float r = size / 2f;
        canvas.drawCircle(r, r, r, paint);
        return result;
    }
 
    @Override
    public String getId()
    {
        return getClass().getName();
    }
 
    // Then we will add a small change to the way our image will be shown:
 
    Glide
        .with(this)
        .load("http://goo.gl/gEgYUd")
        .transform(new CircleTransform(context))
        .into(imageView);


Finally, our image will be rounded. With the help of the Glide library, we can round all images that we need in such a simple way.

Describing the second useful feature of this library that we’ve mentioned above, which is cashing, we can mention that Glide cashes resized images to the memory or disk. For example, there is an image on the server with a resolution of 1000*1000 pixels and your application has image view with a resolution of 100*100 pixels. The library will resize downloaded image to 100*100 pixels and will cash it with such resolution. In case your application will need to show this image again, it will automatically get this image from cash and will show it immediately. The library won’t need to resize the image again because it is already resized in cash.
More information about useful features of this library you can read on Glide official web-page.

Retrofit

We can’t imagine an application that is not connected to the web-server or some informational web-source. Retrofit is a type-safe HTTP client for Android and Java. We use this library to create HTTP request to the server.
You need only one row of code to include the library to your current project:




compile 'com.squareup.retrofit2:retrofit:2.1.0'


Let’s test it out on a simple example, where we will receive a list of emojis from GitHub.
Firstly, we add the following row to our gradle file:

compile ‘com.squareup.retrofit2:converter-gson:2.1.0’

We have added gson converter to our project allowing the library automatically convert the result of the request to the custom object.
Then we create ServiceGenerator class:




public class ServiceGenerator {
    public static final String API_BASE_URL = "https://api.github.com";
 
    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
 
    private static Retrofit.Builder builder = new Retrofit.Builder()
                                  .baseUrl(API_BASE_URL)
                                  .addConverterFactory(GsonConverterFactory.create());
 
    public static S createService(Class serviceClass)
    {
        Retrofit retrofit = builder.client(httpClient.build()).build();
        return retrofit.create(serviceClass);
    }
}


This class defines one method to create a basic REST adapter for a given class/interface.
The following code defines the RestClient and a method to request the list of emojis.

public interface RestClient {
@GET("/emojis")
Call& lt;
Map& gt;
getEmojis();
}

Then we change our onButtonClick method:




@OnClick(R.id.button)
public void onButtonClick()
{
    textView.setText(text);
 
    RestClient restClient = ServiceGenerator.createService(RestClient.class);
 
    Call& lt;
    Map& gt;
    request = restClient.getEmojis();
    request.enqueue(new Callback& lt; Map& gt; () {
        @Override
        public void onResponse(Call & lt; Map & gt; call,
                                                    Response & lt;
                               Map & gt; response)
        {
            if (response != null & amp; & response.body() != null) {
                imageAdapter.setData(new ArrayList(response.body().values()));
            }
        }
 
        @Override
        public void onFailure(Call & lt; Map & gt; call, Throwable t)
        {
            t.printStackTrace();
        }
    });
}
 
// ImageAdapter is an adapter for GridView.
// Listening of method getView is located below:
 
@Override
public View getView(int i, View view, ViewGroup viewGroup)
{
    ImageView imageView;
    if (view == null) {
        imageView = new ImageView(context);
        imageView.setLayoutParams(new GridView.LayoutParams(200, 200));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setPadding(8, 8, 8, 8);
    }
    else {
        imageView = (ImageView)view;
    }
 
    Glide
        .with(context)
        .load(imageUrls.get(i))
        .into(imageView);
 
    return imageView;
}


Now when we click on the Click Me button – we will see a list of emojis below.

Retrofit is a powerful library as it contains many useful features. You can read more detailed review of this toolkit by following the link.

Realm

Android Realm database is simple to use, yet powerful as the core has been written in C++ and is compiled in the native code. With Realm our models are also schemas/tables for our database. This library was made especially for mobile development, which means, it is targeted on mobile devices only and this is the reason why it is appreciated by developers so much. You can read the detailed review of how to include this library to your project in this article.

To introduce you some features of the library, we will update our abovementioned example. For faster and safer app performance, there are always two databases: the main DB (local) and the remote one. While storing all the objects in the local DB, we need to duplicate them into the remote DB. For this purpose we will need to duplicate the list of emojis we already have and to automatize the whole process of adding and deleting objects from one DB to the other one, we need to write the code pieces, introduced below.

We need to create the object structure (schema) for our database:




public class Emoji extends RealmObject {
    private String imageUrl;
    public Emoji() {}
    public String getImageUrl()
    {
        return imageUrl;
    }
    public void setImageUrl(String imageUrl)
    {
        this.imageUrl = imageUrl;
    }
}


Next, we need to change our ImageAdapter class. We add two methods, which allow to delete and add items to the list.




public void addItem(String imageUrl)
{
    if (this.imageUrls == null)
        this.imageUrls = new ArrayList();
 
    if (this.imageUrls.contains(imageUrl))
        return;
 
    this.imageUrls.add(imageUrl);
    notifyDataSetChanged();
}
 
public void deleteItem(String imageUrl)
{
    if (imageUrl == null || this.imageUrls == null)
        return;
 
    this.imageUrls.remove(imageUrl);
    notifyDataSetChanged();
}


In the MainActivity we create three methods, which operate with emojis objects:




private List getEmojiUrls(final RealmResults emojis)
{
    List result = new ArrayList();
    if (emojis.size() & gt; 0) {
        for (Emoji item : emojis) {
            result.add(item.getImageUrl());
        }
    }
 
    return result;
}
 
private void addEmojiToList(String imageUrl)
{
    final RealmResults existEmojis = realm
                                         .where(Emoji.class)
                                         .equalTo("imageUrl", imageUrl)
                                         .findAll();
    if (existEmojis.size() & gt; 0)
        return;
 
    realm.beginTransaction();
    Emoji emoji = realm.createObject(Emoji.class);
    emoji.setImageUrl(imageUrl);
    realm.commitTransaction();
 
    imageAdapter2.addItem(imageUrl);
}
 
private void removeEmojiFromList(String imageUrl)
{
    imageAdapter2.deleteItem(imageUrl);
 
    realm.beginTransaction();
    final RealmResults existEmojis = realm
                                         .where(Emoji.class)
                                         .equalTo("imageUrl", imageUrl)
                                         .findAll();
    if (existEmojis.size() == 0)
        return;
    existEmojis.deleteAllFromRealm();
 
    realm.commitTransaction();
}


And finally, we change our onCreate method. Here we initialize our database and set a click listener on the item of our list.




@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
 
    Realm.init(this);
    realm = Realm.getDefaultInstance();
 
    imageAdapter1 = new ImageAdapter(this);
    imageAdapter2 = new ImageAdapter(this,
                                     getEmojiUrls(realm.where(Emoji.class).findAll()));
 
    gridView1.setAdapter(imageAdapter1);
    gridView2.setAdapter(imageAdapter2);
 
    gridView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView adapterView, View view, int i, long l)
        {
            addEmojiToList(imageAdapter1.getItem(i).toString());
        }
    });
 
    gridView2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView adapterView, View view, int i, long l)
        {
            removeEmojiFromList(imageAdapter2.getItem(i).toString());
        }
    });
}


Now our application looks like introduced in the picture below:

App development challenges

The ready variant of the app you can check out by following our page on GitHub.

Conclusions

Overall, There are so many challenges that companies are facing on the every-day basis while deciding to build a mobile app.

  • Firstly, companies usually don’t have a clear image of how their product should look like, but are sure that they want to create a mobile app.
  • Secondly, lack of designers and developers.
  • Thirdly, lack of project managers to rule the whole process.

There are actually much more challenges to mention, but we can surely say, that every challenge has its solution, and IT companies provide them nowadays on the full-stack basis. Lack of ideas can be compensated with creative UI/UX designers, who will generate it and analysts to assess its potential on the market. Lack of employees can be easily solved with the help of remote mobile developers. With the help of this research, we are now sure, that mobile app development for Android CAN be easier and less time-consuming if developers use third-party libraries for coding. Of course, these are only a couple of them mentioned here, but there surely more of them exist, which are worth using as well.



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads