Tuesday 25 September 2018

Android Architecture Components : Data Binding Part 3

Hi ,
Today I am going to share the third part of Data Binding Demo. You can check out previous posts for more understanding.
In this post I am sharing the data binding in RecyclerView and Adapters.

-> Firstly I created one layout named : friend_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</layout>

-> Now I created one another layout for thumbnail in Grid , named : post_row_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:bind="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="post"
            type="info.databinding.model.Post" />
    </data>

    <android.support.constraint.ConstraintLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/thumbnail"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            android:profileImage="@{post.profileImage}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="H,1:1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>

</layout>

-> I have created the thumbnail layout named: post_row_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:bind="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="post"
            type="info.databinding.model.Post" />
    </data>

    <android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <ImageView
            android:id="@+id/thumbnail"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:scaleType="centerCrop"
            android:profileImage="@{post.profileImage}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="H,1:1"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </android.support.constraint.ConstraintLayout>

</layout>

-> Now let's move to entity part , named : Post.java

public class Post {
    String profileImage;
    public String getProfileImage() {
        return profileImage;
    }

    public void setProfileImage(String profileImage) {
        this.profileImage = profileImage;
    }

    @BindingAdapter({"android:profileImage"})
    public static void loadImage(ImageView view, String imageUrl) {
        // If you consider Picasso, follow the below
        Picasso.with(view.getContext()).
                load(imageUrl).
                placeholder(R.drawable.ic_launcher_background).
                into(view);
    }

}

 -> The adapter class will be named : PostsAdapter.java

public class PostsAdapter extends RecyclerView.Adapter<PostsAdapter.ViewHolder> {
    ArrayList<Post> list = new ArrayList<>();
    Activity activity ;
    LayoutInflater mLayoutInflator;

    class ViewHolder extends RecyclerView.ViewHolder{
       PostRowLayoutBinding postBinding;
        public ViewHolder(PostRowLayoutBinding itemBinding) {
            super(itemBinding.getRoot());
            this.postBinding = itemBinding;
        }
    }
    public PostsAdapter(ArrayList<Post> list, Activity friendsListActivity) {
        this.list = list;
        this.activity = friendsListActivity;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        if (mLayoutInflator == null) {
            mLayoutInflator = LayoutInflater.from(parent.getContext());
        }
        PostRowLayoutBinding binding = DataBindingUtil.inflate(mLayoutInflator,R.layout.post_row_layout,parent,false);
        return new ViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
      
       holder.postBinding.setPost(list.get(position));
       holder.postBinding.thumbnail.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               Toast.makeText(activity,position+" Friends clicked!!",Toast.LENGTH_LONG).show();
           }
       });
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

}

Now the activity class , is named as : FriendsListActivity.class

public class FriendsListActivity extends AppCompatActivity {

    ArrayList<Post> aryList =new ArrayList<>();
    FriendLayoutBinding dataBinding;
    RecyclerView recyclerView;
    PostsAdapter mAdapter;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dataBinding = DataBindingUtil.setContentView(this, R.layout.friend_layout);
        initViews();
    }

    private void initViews() {
        recyclerView = dataBinding.recyclerView;
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
        recyclerView.addItemDecoration(new GridSpacingItemDecoration(3, Utils.dpToPx(4,getApplicationContext()), true));
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setNestedScrollingEnabled(false);
        mAdapter = new PostsAdapter(addFriends(), this);
        recyclerView.setAdapter(mAdapter);
    }

    private ArrayList<Post> addFriends() {
        Post post = new Post();
        post.setProfileImage("https://www.ienglishstatus.com/wp-content/uploads/2018/04/profile-images-for-lover.jpg");
        aryList.add(post);

        Post post1 = new Post();
        post1.setProfileImage("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRLGja2adSQA0iRqBPSP16wx-9QCHK7P0ADoFRAjKfo4elX5unVpg");
        aryList.add(post1);

        Post post2 = new Post();
        post2.setProfileImage("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSm92-cGpGAlpNqJPHzWhSA_p83pkxvQjsLXMrGN1uX8Fw36Zha");
        aryList.add(post2);

        Post post3 = new Post();
        post3.setProfileImage("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRRMXMX3L3ENBdFykfCjGVXomO8qXa082hm80ZAJJIYjNw6pVap");
        aryList.add(post3);

        Post post4 = new Post();
        post4.setProfileImage("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRaAPF9U-hEs5XN_WcGS25NZvaWTAQCklIoi8OJ_aKQMHmf0RdF");
        aryList.add(post4);

        Post post5 = new Post();
        post5.setProfileImage("https://avatarfiles.alphacoders.com/665/66525.jpg");
        aryList.add(post5);

        Post post6 = new Post();
        post6.setProfileImage("https://dp.profilepics.in/profile-pictures-for-facebook-whatsapp/stylish-profile-pics/stylish-profile-pics-for-whatsapp-facebook-05.jpg");
        aryList.add(post6);

        Post post7 = new Post();
        post7.setProfileImage("https://www.androidcrush.com/wp-content/uploads//2016/10/Hope-Whatsapp-Images-Free-Download-1.png");
        aryList.add(post7);

        Post post8 = new Post();
        post8.setProfileImage("https://i.pinimg.com/originals/53/54/f7/5354f750a2816333f42efbeeacb4e244.jpg");
        aryList.add(post8);

        Post post9 = new Post();
        post9.setProfileImage("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSDEDfz0OsWGMtJJH1MuG0Deaxmr7kEsgwU9XtLbW4pZLe8_nYuLQ");
        aryList.add(post9);

        return aryList;
    }
}

Here I have added some random image urls to show the thumbnails in grid.That's it.

Monday 24 September 2018

Android Architecture Components : Data Binding Part 2

Hi ,

In previous post , I have explained about data binding at initial level, now going forward I am going to share the demo to bind ImageView , with the help of Data Binding.

Now firstly enable the dataBinding element in build.gradle .

Add Picasso dependency in build.gradle as well .

implementation 'com.squareup.picasso:picasso:2.5.2'

After that , create an entity class , named ProfilePicEntity :

public class ProfilePicEntity extends BaseObservable {
    String profileImage;

    public String getProfileImage() {
        return profileImage;
    }

    public void setProfileImage(String profileImage) {
        this.profileImage = profileImage;
        notifyPropertyChanged(BR.profile);
    }

    @BindingAdapter({"android:profileImage"})
    public static void loadImage(ImageView view, String imageUrl) {
        // If you consider Picasso, follow the below
        Picasso.with(view.getContext()).
                load(imageUrl).
                placeholder(R.drawable.ic_launcher_background).
                into(view);
    }

}

Here in above class , I have one variable , with its getter/setter methods and one another method to load image .This method is helpful to load image when we pass url in ImageView setProfileImage method.
 @BindingAdapter({"android:profileImage"}) -> this is used to define the attribute which is used in layout to setImage by ImageView Tag.

Now Let's move to layout named : image_view_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="com.demo.databinding.utils.Utils" />
        <import type="android.view.View"/>
        <variable
            name="profile"
            type="com.demo.databinding.model.ProfilePicEntity">              </variable>

        <variable name="handlers"
           type="com.demo.databinding.ImageViewActivity.MyHandlers"> </variable>
    </data>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="20dp">


            <ImageView
                android:id="@+id/imageView"
                android:layout_width="300dp"
                android:layout_height="300dp"
                android:layout_gravity="center_horizontal"
                android:scaleType="fitXY"
                android:profileImage="@{profile.profileImage}"
               tools:srcCompat="@tools:sample/backgrounds/scenic[3]" />

            <Button
                android:id="@+id/button2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Change Image"
                android:onClick="@{(view)->   handlers.onClickButton(imageView)}"
                android:layout_margin="10dp"/>
        </LinearLayout>


</layout>

Here in above layout , we have defined the entity class variable name as -> profile and Handler is named as -> handlers

Now I have created a java class named: ImageViewActivity.java

public class ImageViewActivity extends AppCompatActivity {

    ImageViewLayoutBinding imageViewLayoutBinding;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        imageViewLayoutBinding = DataBindingUtil.setContentView
                (this, R.layout.image_view_layout);

        ProfilePicEntity profilePicEntity = new ProfilePicEntity();
        profilePicEntity.setProfileImage("https://cdn.iconscout.com/icon/free/png-256/avatar-373-456325.png");

        imageViewLayoutBinding.setProfile(profilePicEntity);

        MyHandlers myHandlers = new MyHandlers(this);
        imageViewLayoutBinding.setHandlers(myHandlers);
    }

    public class MyHandlers{
        public MyHandlers(ImageViewActivity activity) {
        }

        public void onClickButton(ImageView view){
            Toast.makeText(getApplicationContext(),"Button is Clicked!",Toast.LENGTH_LONG).show();
            ProfilePicEntity profilePicEntity = new ProfilePicEntity();
            profilePicEntity.setProfileImage("https://www.attractivepartners.co.uk/wp-content/uploads/2017/06/profile.jpg");
            imageViewLayoutBinding.setProfile(profilePicEntity);
        }

    }

}


Above in java class , I am setting one image url at loading time and after click the button to change the image , again setting another image url on that imageView. That's it . Paste this code and run it , let me know if you face any problem . In next post I will share the data Binding in Adapters. Till then Happy Coding :)






  

Android Architecture Components : Data Binding Part 1

Hi ,

Today I am going to share the demo for data binding . According to android official docs: The Data Binding Library is a support library that allows you to bind UI components in your layout to data sources in your app using a declarative format rather than programmatically.

So as it is mentioned , this library is basically used to bind view of layout to view of activity, without using findViewById() .

Let's start with few coding, here I am showing a simple demo with 3 textviews and 1 profile picture form layout :

-> Firstly we need to download lib in Android SDK Manager : Support Repository 

-> Add Data Binding element into build.gradle :


android {
    dataBinding {
        enabled = true    }

-> Now let's design the layout , here you have to notice one thing , that parent tag of all layout should be :  <layout> </layout> only. This is used to create the by default binding class for each layout.If you forgot to add this tag as the parent tag , so we would not be able to get the binding class of this layout , in our activity class :

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="com.demo.databinding.utils.Utils" />
        <import type="android.view.View"/>
        <variable
            name="user"
            type="com.demo.databinding.model.User"></variable>

        <variable 
            name="handlers"
            type="com.demo.databinding.MainActivity.MyHandlers"></variable>
    </data>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="10dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="20dp">


        <TextView
            android:id="@+id/textView2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{Utils.capitalize(user.name)}"
            android:onClick="@{(view)-> handlers.onTextClicked(view)}"
            android:layout_margin="10dp"
            android:textSize="18sp"
            android:clickable="true"
            android:textColor="@color/colorAccent"/>

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.email}"
            android:onClick="@{(view)-> handlers.showEmail(view,user.email)}"
            android:layout_margin="10dp"
            android:textSize="18sp"
            android:textColor="@color/colorAccent"/>

        <TextView
            android:id="@+id/textView3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{user.phoneNumber}"
            android:onClick="@{() -> handlers.onClickNumber()}"
            android:layout_margin="10dp"
            android:textSize="18sp"
            android:textColor="@color/colorAccent"/>

        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Submit"
            android:layout_margin="10dp"
            android:textSize="18sp"
            android:onClick="@{()-> handlers.onSubmitButtonClicked(textView2, textView,textView3)}"
            android:textColor="@color/colorAccent"/>


    </LinearLayout>
    </ScrollView>
</layout>

The above layout (activity_main.xml), is having few textviews and button with one imageview,here we have used some tags, take a look:

-> <layout> - This tag is used as a parent tag of a layout, for data-binding it is compulsory.
-> <data> -  This tag is used to import any class for src to layout .
-> @{} - > It is used to define the particular callback on call any event.

Here in textviews we are setting different types of Strings/Numbers , which are managed by JAVA class , which we will show you further :

  1. android:text="@{Utils.capitalize(user.name)}"
  2. android:text="@{user.email}"
  3. android:text="@{user.phoneNumber}"
In above it is clear that User is an entity and name, email and phoneNumber has been set here like this.


Also in these 3 textviews we have different types of call onClick event , that are:

  1. onClick="@{(view)-> handlers.onTextClicked(view)}"
  2. onClick="@{(view)-> handlers.showEmail(view,user.email)}"
  3. onClick="@{() -> handlers.onClickNumber()}"
In Pt 1: We are passing the same textview object on click that textView.

In Pt.2: We are passing that textView and  email , which are setted by JAVA class (will explain you later)

In Pt. 3: We are calling this method without any parameters.

Now Let's take a look on User.class(entity class) :


public class User extends BaseObservable {
    String name;
    String email;
    String phoneNumber;

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

    @Bindable
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
        notifyPropertyChanged(BR.email);
    }

    @Bindable
    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
        notifyPropertyChanged(BR.phoneNumber);
    }
   
}

-> We have added a method in Utils class as well:

 public static String capitalize(String text) {
        return text.toUpperCase();
    }

-> Now let's move to MainActivity.class:

public class MainActivity extends AppCompatActivity {

    User user;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding dataBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);

        user = new User();
        user.setName("XYZ");
        user.setEmail("xyz@gmail.com");
        user.setPhoneNumber("9876543210");
       

        dataBinding.setUser(user);
        MyHandlers handlers = new MyHandlers(MainActivity.this);
        dataBinding.setHandlers(handlers);
    }

    public class MyHandlers{
        public MyHandlers(MainActivity activity) {
        }

        public void onTextClicked(View view){
            Toast.makeText(getApplicationContext(),"Text is Clicked!",Toast.LENGTH_LONG).show();
        }

        public void showEmail(View view, String email){
            Toast.makeText(getApplicationContext(),email+" is entered !!",Toast.LENGTH_LONG).show();
        }

        public void onClickNumber(){
            Toast.makeText(getApplicationContext(),"Phone number is clicked!!",Toast.LENGTH_LONG).show();
        }

        public void onSubmitButtonClicked(TextView name, TextView email, TextView phoneNumber){
            User user  =  new User();
            user.setName("PQR");
            user.setEmail("pqr@gmail.com");
            user.setPhoneNumber("1234567890");
            name.setText("PQR");
            email.setText("pqr@gmail.com");
            phoneNumber.setText("1234567890");
            Toast.makeText(getApplicationContext(),"Submit is clicked!!",Toast.LENGTH_LONG).show();

        }

        
    }

}


-> Above in MainActivity , we have set Content View , we have to call setContentView from DataBindingUtil class.

After that we will set all the variables of Entity class, in our case it is User.java.
then set it to ActivityMainBinding  class(it is a generated class mainly used for Binding data) 
Set the Handlers  object to this class also. That's it. Run the code and enjoy the data binding experience :) .For ImageView setting I will explain in next post ,till then Happy Coding :) 






Advanced Kotlin Coroutines : Introduction

 Hi,  Today I am unwraping the topic in Kotin world i.e. Coroutine . If you want to get started with Kotlin coroutine and ease your daily de...