Wednesday, 30 December 2015

TableLayout like ListView (Multi Column ListView)

Many Android developers mess up in building a Multi column ListView, which looks similar to a table layout in android.
So in this tutorial I am showing you how to create a multi column list view.

Output : 



Step 1 : Create a new project by going to File ⇒ New Android Application Project. Fill all the details and name your activity as MainActivity. (eclipse)

Step 2 : Design the activity_main.xml layout for MainActivity under layout folder as shown below

 activity_main.xml
 
    <LinearLayout
        android:id = "@+id/relativeLayout1"
        android:layout_width = "fill_parent"
        android:layout_height = "wrap_content"
        android:background = "@color/colorCell" >

        <TextView
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_weight = "1"
            android:gravity = "center"
            android:padding = "5dp"
            android:text = "@string/sNo"
            android:textColor = "#ffffff" />

        <TextView
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_weight = "2"
            android:gravity = "center"
            android:padding = "5dp"
            android:text = "@string/product"
            android:textColor = "#ffffff"/ >

        <TextView
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_weight = "1.5"
            android:gravity = "center"
            android:padding = "5dp"
            android:text = "@string/category"
            android:textColor = "#ffffff" />

        <TextView
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_weight = "1"
            android:gravity = "center"
            android:padding = "5dp"
            android:text = "@string/price"
            android:textColor = "#ffffff" />
    </LinearLayout>

    <ListView
        android:id = "@+id/listview"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:divider = "@null"/>

Step 3 : Create a xml file under drawable-hdpi and name it as cell_shape.xml as shown below.

  cell_shape.xml

 <layer-list xmlns:android = "http://schemas.android.com/apk/res/android">

    <item
        android:left = "-2dp"
        android:top = "-2dp">
        <shape android:shape = "rectangle" >
            <solid android:color = "@android:color/transparent" />

            <stroke
                android:width = "1dp"
                android:color = "@color/colorCell" />
        </shape>
    </item>
</layer-list

Step 4 : Create a new class under src/package. Right Click on src/package (com.example.multicolumnlistview) ⇒ New ⇒ Class and name it as Model.java and fill it with following code.

Model.java

public class Model {

    private String sNo;
    private String product;
    private String category;
    private String price;

    public Model(String sNo, String product, String category, String price) {
        this.sNo = sNo;
        this.product = product;
        this.category = category;
        this.price = price;
    }

    public String getsNo() {
        return sNo;
    }

    public String getProduct() {
        return product;
    }

    public String getCategory() {
        return category;
    }

    public String getPrice() {
        return price;
    }
}

Step 5 : Create a new xml file under res/layout. Right Click on res/layout ⇒ New ⇒ Android XML File and name it as listview_row.xml and fill it with following code. This layout is the custom layout inside list adapter.

listview_row.xml 
 
    <LinearLayout
        android:id = "@+id/relativeLayout1"
        android:layout_width = "fill_parent"
        android:layout_height = "wrap_content"
        android:background = "@color/colorCell" >

        <TextView       
            android:id = "@+id/sNo"      
            android:layout_width = "0dp"
            android:layout_height = "match_parent"
            android:layout_weight = "1"
            android:background = "@drawable/cell_shape"
            android:ellipsize = "end"
            android:padding = "5dp"
            android:text = "@string/sNo"
            android:singleLine = "true" />

        <TextView       
            android:id = "@+id/product"      
            android:layout_width = "0dp"
            android:layout_height = "match_parent"
            android:layout_weight = "2"
            android:background = "@drawable/cell_shape"
            android:ellipsize = "end"
            android:padding = "5dp"
            android:text = "@string/product"
            android:singleLine = "true" />

        <TextView       
            android:id = "@+id/category"      
            android:layout_width = "0dp"
            android:layout_height = "match_parent"
            android:layout_weight = "1.5"
            android:background = "@drawable/cell_shape"
            android:ellipsize = "end"
            android:padding = "5dp"
            android:text = "@string/category"
            android:singleLine = "true" />

         <TextView       
            android:id = "@+id/price"      
            android:layout_width = "0dp"
            android:layout_height = "match_parent"
            android:layout_weight = "1"
            android:background = "@drawable/cell_shape"
            android:ellipsize = "end"
            android:padding = "5dp"
            android:text = "@string/price"
            android:singleLine = "true" />
    </LinearLayout>

 Creating custom adapter for list view : 
Step 6 : Create a new class under src/package. Right Click on src/package (com.example.multicolumnlistview) ⇒ New ⇒ Class and name it as listviewAdapter.java and fill it with following code.


listviewAdapter.java

public class listviewAdapter extends BaseAdapter {

     public ArrayList<Model> productList;
     Activity activity;

    public listviewAdapter(Activity activity, ArrayList<Model> productList) {
        super();
        this.activity = activity;
        this.productList = productList;
    }

    @Override
    public int getCount() {
        return productList.size();
    }

    @Override
    public Object getItem(int position) {
       return productList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    private class ViewHolder {
        TextView mSNo;
        TextView mProduct;
        TextView mCategory;
        TextView mPrice;
    }

    @Override
     public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;
        LayoutInflater inflater = activity.getLayoutInflater();

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.listview_row, null);
            holder = new ViewHolder();
            holder.mSNo = (TextView) convertView.findViewById(R.id.sNo);
            holder.mProduct = (TextView) convertView.findViewById(R.id.product);
            holder.mCategory = (TextView) convertView
                    .findViewById(R.id.category);
            holder.mPrice = (TextView) convertView.findViewById(R.id.price);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        Model item = productList.get(position);
        holder.mSNo.setText(item.getsNo().toString());
        holder.mProduct.setText(item.getProduct().toString());
        holder.mCategory.setText(item.getCategory().toString());
        holder.mPrice.setText(item.getPrice().toString());

        return convertView;
    }
}

 Step 7 : Add the following code in MainActivity.

MainActivity.java

    private ArrayList<Model> productList;

  @Override
    proctected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        productList = new ArrayList<Model>();
        ListView lview = (ListView) findViewById(R.id.listview);
        listviewAdapter adapter = new listviewAdapter(this, productList);
        lview.setAdapter(adapter);

        populateList();

        adapter.notifyDataSetChanged();
       
        lview.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

                String sno = ((TextView)view.findViewById(R.id.sNo)).getText().toString();
                String product = ((TextView)view.findViewById(R.id.product)).getText().toString();
                String category = ((TextView)view.findViewById(R.id.category)).getText().toString();
                String price = ((TextView)view.findViewById(R.id.price)).getText().toString();
               
                Toast.makeText(getApplicationContext(),
                          "S no : " + sno +"\n"
                        +"Product : " + product +"\n"
                        +"Category : " +category +"\n"
                        +"Price : " +price, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void populateList() {

        Model item1, item2, item3, item4, item5;

        item1 = new Model("1", "Apple (Northern Spy)", "Fruits", "₹. 200");
        productList.add(item1);

        item2 = new Model("2", "Orange (Sunkist navel)", "Fruits", "₹. 100");
        productList.add(item2);

        item3 = new Model("3", "Tomato", "Vegetable", "₹. 50");
        productList.add(item3);

        item4 = new Model("4", "Carrot", "Vegetable", "₹. 80");
        productList.add(item4);

        item5 = new Model("5", "Banana (Cavendish)", "Fruits", "₹. 100");
        productList.add(item5);
    }

Checkout the live demo :



Source code : Click here to download. 

Source link

As always, Thanks a lot for reading...

Don't forget to share this post if you found it interesting!
If you find something to add to this post? or any other quick thoughts/hints that you think people will find useful? Share it in the comments & feedback's are most welcome. 

Wednesday, 23 December 2015

How to execute Multiple Async Task at the same time

AsyncTask Overview

AsyncTask is an abstract Android class which helps the Android applications to handle the Main UI thread in an efficient way. AsyncTask class allows us to perform long lasting tasks/background operations and show the result on the UI thread without affecting the main thread.

An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called onPreExecute, doInBackground, onProgressUpdate and onPostExecute.



 onPreExecute():
 This method is invoked before doInBackground method is called. This method is normally used to setup the progress bar in the UI.

doInBackground():
This method contains the code running for long time (For eg: Downloading files from internet or Uploading files to cloud server and so on). When execute method is called in UI main thread, this method is called with the parameters passed.

 onProgressUpdate():
This method is called by publishProgress at anytime from doInBackground. This method can be used to display any form of progress in the user interface.

onPostExecute():
This method is executed after doInBackground method completes processing. Result of the doInBackground is passed to this method.

The three generic types used by an asynchronous task are the following:
  1. Params, the type of the parameters sent to the task upon execution.
  2. Progress, the type of the progress units published during the background computation.
  3. Result, the type of the result of the background computation.
 Note : AsyncTask uses a thread pool pattern for running the stuff from doInBackground(). When first introduced the pool size was just 1, meaning no parallel computations for a bunch of AsyncTasks, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. 
The pool size is 5, so at most 5 AsyncTasks can run simultaneously.
Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

 If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.

reference: AsyncTask | Android Developers
                                                                                                                                                  

This tutorial shows you how to execute multiple Async task at the same time parallel, and update the listview.

The first three ProgressBars updated by AsyncTask execute in normal approach by calling execute(), the last two ProgressBar updated by AsyncTask execute in parallel.


 MainActivity.java

 
public class MainActivity extends Activity {

    private static String url = "replace your request url here";

   
private static JSONArray contacts = null;
    private static ArrayList<HashMap<String, String>> contactList;
    private ListView mListView;
    private LazyAdapter adapter;
   
private ArrayList<HashMap<String, String>> datumList;

    public static final String TAG_DOCTORS = "doctor_details";
   
public static final String TAG_ID = "doc_id";
   
public static final String TAG_NAME = "name";
   
public static final String TAG_SPECIALIST= "specialist";
   
public static final String TAG_QUAL = "qualification";
   
public static final String TAG_EXP = "experience";
   
public static final String TAG_BRANCH = "branch";
   
public static final String TAG_THUMB_URL = "thumb_url";

   
public class MyAsyncTask extends AsyncTask<String, Integer, String> {

        ProgressBar myProgressBar;
        ImageView error, success;

       
public MyAsyncTask(ProgressBar target, ImageView error, ImageView success) {
            myProgressBar = target;
            error = error;
            success = success;          
        }

        @Override
        protected String doInBackground(String... urls) {
          
            String result = "success";
            ServiceHandler sh = new ServiceHandler();
            try{
            String jsonStr = sh.makeServiceCall(urls[0], ServiceHandler.GET);
            Log.d("Response: ", "> " + jsonStr);

            for (int i = 0; i < urls.length; i++) {
                   
datumList = parse(jsonStr);
                    publishProgress((int) (((i + 1) / (float) urls.length) * 100));  
            }
            } catch (Exception e) {
                e.printStackTrace();
                result = "fail";
            }
            return result;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            myProgressBar.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(String result) {
            Log.e("Result size", result);
            if(!(result.equals("fail")))
            {
                this.success.setVisibility(View.VISIBLE);
            }              
            else if(result.equals("fail"))
            {
                this.myProgressBar.getProgressDrawable().setColorFilter(Color.RED,       Mode.SRC_IN);
                this.error.setVisibility(View.VISIBLE);
            }
           
adapter.notifyDataSetChanged();
        }
    }

    Button buttonStart;
    ProgressBar progressBar1, progressBar2, progressBar3, progressBar4, progressBar5;
    MyAsyncTask asyncTask1, asyncTask2, asyncTask3, asyncTask4, asyncTask5;
    ImageView error1, error2, error3, error4, error5, success1, success2, success3, success4,       success5;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

       
contactList = new ArrayList<HashMap<String, String>>();
       
adapter = new LazyAdapter(MainActivity.this, contactList);

       
mListView = (ListView) findViewById(R.id.listView1);
       
mListView.setTextFilterEnabled(true);
       
mListView.setAdapter(adapter);

        intitView();
      
        buttonStart.setOnClickListener(new OnClickListener() {

            @Override
           
public void onClick(View v) {
                asyncTask1 = new MyAsyncTask(progressBar1,error1, success1);
                asyncTask1.execute("brokenUrl");
                asyncTask2 = new MyAsyncTask(progressBar2,error2, success2);
                asyncTask2.execute(url);
                asyncTask3 = new MyAsyncTask(progressBar3,error3, success3);
                asyncTask3.execute(url);
                asyncTask4 = new MyAsyncTask(progressBar4,error4, success4);
                StartAsyncTaskInParallel(asyncTask4,url);
                asyncTask5 = new MyAsyncTask(progressBar5,error5, success5);
                StartAsyncTaskInParallel(asyncTask5,"brokenUrl");
            }
        });
    }
 
    private void intitView() {
      
       
datumList = new ArrayList<HashMap<String, String>>();
      
        progressBar1 = (ProgressBar) findViewById(R.id.progressbar1);
        progressBar2 = (ProgressBar) findViewById(R.id.progressbar2);
        progressBar3 = (ProgressBar) findViewById(R.id.progressbar3);
        progressBar4 = (ProgressBar) findViewById(R.id.progressbar4);
        progressBar5 = (ProgressBar) findViewById(R.id.progressbar5);

        error1 = (ImageView) findViewById(R.id.error1);
        error2 = (ImageView) findViewById(R.id.error2);
        error3 = (ImageView) findViewById(R.id.error3);
        error4 = (ImageView) findViewById(R.id.error4);
        error5 = (ImageView) findViewById(R.id.error5);
      
        success1 = (ImageView) findViewById(R.id.success1);
        success2 = (ImageView) findViewById(R.id.success2);
        success3 = (ImageView) findViewById(R.id.success3);
        success4 = (ImageView) findViewById(R.id.success4);
        success5 = (ImageView) findViewById(R.id.success5);
      
        buttonStart = (Button) findViewById(R.id.start);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
   
private void StartAsyncTaskInParallel(MyAsyncTask task, String url) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
        else
            task.execute();
    }

   
public static ArrayList<HashMap<String, String>> parse(String jsonStr){

        if (jsonStr != null) {
            try {
                JSONObject jsonObj = new JSONObject(jsonStr);

               
contacts = jsonObj.getJSONArray(TAG_DOCTORS);

                for (int i = 0; i <
contacts.length(); i++) {
                    JSONObject jsonObject =
contacts.getJSONObject(i);
                  
                    String id =
jsonObject.getString(TAG_ID);
                    String name =
jsonObject.getString(TAG_NAME);
                    String branch =
jsonObject.getString(TAG_BRANCH);
                    String
specialist = jsonObject.getString(TAG_SPECIALIST);
                    String quali =
jsonObject.getString(TAG_QUAL);
                    String expe =
jsonObject.getString(TAG_EXP);
                    String img_url =
jsonObject.getString(TAG_THUMB_URL);

                    HashMap<String, String> contact = new HashMap<String, String>();

                    contact.put(
TAG_ID, id);
                    contact.put(
TAG_NAME, name);
                    contact.put(TAG_BRANCH, branch);
                    contact.put(TAG_
SPECIALIST, specialist);
                    contact.put(TAG_QUAL, quali);

                    contact.put(TAG_EXP, expe);
                    contact.put(TAG_THUMB_URL,
img_url);

                   
contactList.add(contact);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return
contactList;
    }
}



 activity_main.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidparallelasynctask.MainActivity" >

    <Button
        android:id="@+id/start"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Start" />

    <
LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="5dp" >

        <ProgressBar
            android:id="@+id/progressbar1"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="10"
            android:indeterminate="false"
            android:max="100"
            android:progress="0" />

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/success1"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginLeft="2dp"
                android:layout_marginStart="2dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/success"
                android:visibility="invisible" >
            </ImageView>

            <ImageView
                android:id="@+id/error1"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/error"
                android:visibility="invisible" >
            </ImageView>
        </FrameLayout>
    </
LinearLayout>

    <
LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="5dp" >

        <ProgressBar
            android:id="@+id/progressbar2"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="10"
            android:max="100"
            android:progress="0" />

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/success2"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginLeft="2dp"
                android:layout_marginStart="2dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/success"
                android:visibility="invisible" >
            </ImageView>

            <ImageView
                android:id="@+id/error2"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/error"
                android:visibility="invisible" >
            </ImageView>
        </FrameLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="5dp" >

        <ProgressBar
            android:id="@+id/progressbar3"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="10"
            android:indeterminate="false"
            android:max="100"
            android:progress="0" />

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/success3"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginLeft="2dp"
                android:layout_marginStart="2dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/success"
                android:visibility="invisible" >
            </ImageView>

            <ImageView
                android:id="@+id/error3"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/error"
                android:visibility="invisible"/>
        </FrameLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="5dp" >

        <ProgressBar
            android:id="@+id/progressbar4"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="10"
            android:indeterminate="false"
            android:max="100"
            android:progress="0" />

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/success4"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginLeft="2dp"
                android:layout_marginStart="2dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/success"
                android:visibility="invisible" />

            <ImageView
                android:id="@+id/error4"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/error"
                android:visibility="invisible"/>
        </FrameLayout>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        android:padding="5dp" >

        <ProgressBar
            android:id="@+id/progressbar5"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="10"
            android:indeterminate="false"
            android:max="100"
            android:progress="0" />

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/success5"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_marginLeft="2dp"
                android:layout_marginStart="2dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/success"
                android:visibility="invisible" />

            <ImageView
                android:id="@+id/error5"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:contentDescription="@string/app_name"
                android:src="@drawable/error"
                android:visibility="invisible" />
        </FrameLayout>
    </LinearLayout>

    <ListView
        android:id="@+id/listView1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>



Live Demo : 



Source code : Click here to download. 

Source link : Android-er

As always, Thanks a lot for reading...
Don't forget to share this post if you found it interesting!
If you find something to add to this post? or any other quick thoughts/hints that you think people will find useful? Share it in the comments & feedback's are most welcome.