Showing posts with label Context and Application Context in Android. Show all posts
Showing posts with label Context and Application Context in Android. Show all posts

Sunday, March 23, 2014

Context and Application Context in Android Tutorial

Context and Application Context in Android Tutorial

Purpose of Context and Application Context in Android is explained in this section
Context:
                                                                          Its the context of current state of the application/object. It lets newly created objects understand what has been going on. Typically you call it to get information regarding another part of your program (activity, package/application)You can get the context by invoking getApplicationContext()getContext()getBaseContext() or this (when in the activity class).
Things that involve context are
1.    Loading a resource.
2.    Launching a new activity.
3.    Creating views.
4.obtaining system service
Application Context
Application class extends Context class.Every Application has a context, and Android guarantees that Application context will exist as a instance across your application.Many times you may need to store the state of your app or a need a variable across multiple Activities,services and other java classes . Android provides an easy option for doing this – the global application context.


Custom adapters
Android Adapter is a bridge between the View (e.g. ListView) and the underlying data for that view. An adapter manages the data and adapts the data to the individual rows (listItems) of the view.We bind the adapter with Android listview via setAdapter method.Once we have a reference to the view, we can get the data from the data source either in an Array list or a cursor. We can then bind the data to the view items. All this is done in getView Method.By default, ArrayAdapter expects a Layout with single TextView. If you want to use more complex views, please avoid ArrayAdapter and use custom adapter.ArrayAdapter is also an implementation of BaseAdapter
BaseAdapter is a common base class of a general implementation for an Adapter that can be used in ListView. BaseAdapter can be extended to create a custom Adapter to suit your need of building a custom listitem.
Understanding Custom Adapter Methods
Methods of the custom adapter.are detailed below.
  • getCount() : This method tells the listview the number of rows it will require. This count can come from your data source. It can be the size of your Data Source. If you have your datasource as a list of objects, this value will be the size of the list.
  • Object getItem(int arg0): We have 2 method implementation of getItem. This method returns an object. This method helps ListView to get data for each row. The parameter passed is the row number starting from 0. In our List of Objects, this method will return the object at the passed index.
  • long getItemId(int arg0) : You can ignore this method. It just returns the same value as passed. This in general helps ListView to map its rows to the data set elements.
  • getView : This is the most important method. This method will be called to get the View for each row. This is the method where we can use our custom listitem and bind it with the data. The fist argument passed to getView is the listview item position ie row number. The second parameter is recycled view reference(as we know listview recycles a view, you can confirm through this parameter). Third parameter is the parent to which this view will get attached to. 
Data Source can any custom object(user defined class objects).
The Demonstrative Project takes product and its price details from user and updates it in to Custom ListView and computes total price of the product added to list.User has choice to delete any item from the list
1.Create  Android project with details as listed in the table below.

Property name
Property value
Project name
SRM_ApplicationContextTutorial
Package name
in.ac.srmuniv.applicationcontextactivities
Activity name
MainActivity
Layout xml name
main

2.Create a java file named ListProductModel.java under the following mentioned package
packagein.ac.srmuniv.applicationcontextjavaclasses;

public class ListProductModel {
    private  String ProductName="";
    private  double price;
    /*********** Set Methods ******************/
    public voidsetProductName(String ProductName)
    {
        this.ProductName = ProductName;
    }

    public void setprice(double price)
    {
        this.price = price;
    }
    /*********** Get Methods ****************/

    public String getProductName()
    {
        return this.ProductName;
    }

    public double getprice()
    {
        return this.price;
    }
}
3.Create a java file named ProductManagerApplication.java under the following mentioned package
packagein.ac.srmuniv.applicationcontextandroidclasses;

importin.ac.srmuniv.applicationcontextjavaclasses.ListProductModel;

import java.util.ArrayList;

importandroid.app.Application;
  
public classProductManagerApplication extends Application{
    privateArrayList<ListProductModel> productsList;
    private double totalPrice;

    @Override
    public void onCreate() {
        super.onCreate();
        if (null == productsList) {
            productsList = new ArrayList<ListProductModel>();
        }
    }

    public voidsetCurrentProducts(ArrayList<ListProductModel> productsList) {
        this.productsList = productsList;
    }

    publicArrayList<ListProductModel> getCurrentProducts() {
        return productsList;
    }

    public voidaddProduct(ListProductModel t) {
        assert(null != t);
        if (null == productsList) {
            productsList = newArrayList<ListProductModel>();
        }
        productsList.add(t);
        calcProductTotal();
    }
    private void calcProductTotal() {
        double price=0.0;
        for(ListProductModel prod : productsList) //use for-each loop
        {
            price +=prod.getprice();
        }
        totalPrice=price;
    }
    public voidremoveProduct(ListProductModel l)
    {
        productsList.remove(l);
        calcProductTotal();
    }
    public double getTotalprice()
    {
        return totalPrice;
    }

}
5.Create a java file named ProductManagerApplication.java under the following mentioned package
packagein.ac.srmuniv.applicationcontextandroidclasses;

importin.ac.srmuniv.applicationcontextactivities.MainActivity;
importin.ac.srmuniv.applicationcontextjavaclasses.ListProductModel;
importin.ac.srmuniv.applicationcontextactivities.R;

import java.util.ArrayList;

importandroid.app.Activity;
importandroid.content.Context;
import android.util.Log;
importandroid.view.LayoutInflater;
import android.view.View;
importandroid.view.View.OnClickListener;
importandroid.view.ViewGroup;
importandroid.widget.BaseAdapter;
importandroid.widget.TextView;

public class CustomAdapter extends BaseAdapter   implements OnClickListener {

    /*********** Declare Used Variables *********/
    private Activity activity;
    privateArrayList<ListProductModel> data;
    private static LayoutInflater inflater=null;
    ListProductModel tempValues=null;
    int i=0;

    /*************  CustomAdapter Constructor *****************/
    publicCustomAdapter(Activity a, ArrayList<ListProductModel> d) {

        /********** Take passed values **********/
        activity = a;
        data=d;


        /***********  Layout inflator to call external xml layout () ***********/
        inflater = ( LayoutInflater )activity.
                getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    /******** What is the size of Passed Arraylist Size ************/
    public int getCount() {

        if(data.size()<=0)
            return 1;
        return data.size();
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }
    public void forceReload() {
        notifyDataSetChanged();
    }

    /********* Create a holder Class to contain inflated xml file elements *********/
    public static class ViewHolder{

        public TextView text;
        public TextView text1;

    }

    /****** Depends upon data size called for each row , Create each ListView row *****/
    public View getView(int position, View convertView, ViewGroup parent) {

        View vi = convertView;
        ViewHolder holder;

        if(convertView==null){

            /****** Inflate product_row.xml file for each row ( Defined below ) *******/
            vi = inflater.inflate(R.layout.product_row, null);

            /****** View Holder Object to contain product_row.xml file elements ******/

            holder = new ViewHolder();
            holder.text = (TextView) vi.findViewById(R.id.text);
            holder.text1=(TextView)vi.findViewById(R.id.text1);


            /************  Set holder with LayoutInflater ************/
            vi.setTag( holder );
        }
        else
            holder=(ViewHolder)vi.getTag();

        if(data.size()<=0)
        {
            holder.text.setText("No Added Product");
            holder.text1.setText("");
        }
        else
        {
            /***** Get each Model object from Arraylist ********/
            tempValues=null;
            tempValues = ( ListProductModel ) data.get( position );

            /************  Set Model values in Holder elements ***********/

            holder.text.setText( tempValues.getProductName());
            holder.text1.setText(  new Double(tempValues.getprice()).toString() );

            /******** Set Item Click Listner for LayoutInflater for each row *******/

            vi.setOnClickListener(new OnItemClickListener( position ));
        }
        return vi;
    }

    @Override
    public void onClick(View v) {
        Log.v("CustomAdapter", "=====Row button clicked=====");
    }

    /********* Called when Item click in ListView ************/
    private classOnItemClickListener  implementsOnClickListener{          
        private int mPosition;

        OnItemClickListener(int position){
            mPosition = position;
        }

        @Override
        public void onClick(View arg0) {


            MainActivity m = (MainActivity)activity;

            /****  Call  onItemClick Method inside MainActivity Class ( See Below )****/

            m.onItemClick(mPosition);
        }              
    }
 }
6.Copy the code  to the file main.xml in res/layout folder 
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="5dp"
        android:paddingBottom="5dp" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:text="@string/addproduct_btn" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/button1"
            android:layout_alignBottom="@+id/button1"
            android:layout_toRightOf="@+id/button1"
            android:text="@string/pricetotal_label"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:text=""
            android:textAppearance="?android:attr/textAppearanceLarge" />

    </RelativeLayout>
        <ListView
            android:id="@+id/list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scrollbars="vertical"
            android:dividerHeight="2dp">
        </ListView>

</LinearLayout>



7.Copy the code  to the file product_row.xml in res/layout folder 
<?xml version="1.0"encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:paddingTop="0dip" android:layout_gravity="top"
            >
            <TableRow>       
               <TextView
                    android:id="@+id/text"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_gravity="left|center_vertical"
                    android:textSize="16sp"
                    android:layout_marginLeft="10dip"
                    android:layout_marginTop="4dip"
                    android:textColor="#000000"
                    android:layout_span="1"
                    />
              </TableRow>
              <TableRow>         
                 <TextView
                    android:text=""
                    android:id="@+id/text1"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"
                    android:layout_weight="1"
                    android:layout_gravity="left|center_vertical"
                    android:textSize="16sp"
                    android:textColor="#000000"
                    android:layout_marginLeft="10dip"
                    android:layout_marginTop="4dip"
                    android:gravity="left"/>
              </TableRow>
            </TableLayout>

8.Copy the code in MainActivity.java. Activity.
package in.ac.srmuniv.applicationcontextactivities;

import in.ac.srmuniv.applicationcontextandroidclasses.CustomAdapter;
import in.ac.srmuniv.applicationcontextandroidclasses.ProductManagerApplication;
import in.ac.srmuniv.applicationcontextjavaclasses.ListProductModel;
import in.ac.srmuniv.applicationcontextactivities.R;

import java.util.ArrayList;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

    ListView list;
    CustomAdapter adapter;    public  ArrayList<ListProductModel> CustomListViewValuesArr = new ArrayList<ListProductModel>();
    private ProductManagerApplication globalVar;
    private TextView total;
    private AlertDialog deleteProductDialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button addProduct=(Button)findViewById(R.id.button1);
        total=(TextView)findViewById(R.id.textView2);
        addProduct.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, AddProductActivity.class);
                startActivity(intent);

            }
        });
        globalVar=(ProductManagerApplication)getApplicationContext();
        
        /******** Take some data in Arraylist ( CustomListViewValuesArr ) ***********/
        setListData();

        //Resources res =getResources();
        list= ( ListView )findViewById( R.id.list );  // List defined in XML ( See Below )

        /**************** Create Custom Adapter *********/
        adapter=new CustomAdapter( thisCustomListViewValuesArr );
        list.setAdapter( adapter );

    }
    @Override
    protected void onResume() {
        super.onResume();
        adapter.forceReload();
        total.setText(new Double(globalVar.getTotalprice()).toString());
    }
    /****** Function to set data in ArrayList *************/
    public void setListData()
    {
        CustomListViewValuesArr =globalVar.getCurrentProducts();
    }
    /*****************  This function used by adapter ****************/
    public void onItemClick(int mPosition)
    {

        if(!CustomListViewValuesArr.isEmpty())
        {
            final int pos=mPosition;

            deleteProductDialog = new AlertDialog.Builder(this)
            .setTitle(R.string.dialogbox_title)
            .setMessage(R.string.dialogbox_message)
            .setNeutralButton(R.string.dialogbox_deletebtnnew AlertDialog.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    deteleProduct(pos);
                }
            })
            .setNegativeButton(android.R.string.cancelnew AlertDialog.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    deleteProductDialog.cancel();
                }
            })
            .create();
            deleteProductDialog.show();
        }

    }
    protected void deteleProduct(int mPosition) {

        ListProductModel tempValues = ( ListProductModel ) CustomListViewValuesArr.get(mPosition);

        globalVar.removeProduct(tempValues);
        adapter.forceReload();
        total.setText(new Double(globalVar.getTotalprice()).toString());
        // SHOW ALERT                 

        Toast.makeText(this,
                ""+tempValues.getProductName()
                +" Removed",
                Toast.LENGTH_LONG)
                .show();
    }
}
9.Copy the code  to the file add_product.xml in res/layout folder 

 <?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:id="@+id/tasks_title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/productname_label"
        android:textAppearance="?android:attr/textAppearanceMedium"
        />
    <EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:id="@+id/task_name"/>

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/productprice_label"
        android:textAppearance="?android:attr/textAppearanceMedium"/>

    <EditText
        android:id="@+id/price"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberDecimal"
        android:ems="10">

        <requestFocus />
    </EditText>
    <Button
        android:id="@+id/add_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/addproduct_btn"/>
    <Button
        android:id="@+id/cancel_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/quitentry_btn"/>
</LinearLayout>
6.Copy the code in AddProductActivity.java. Activity.
packagein.ac.srmuniv.applicationcontextactivities;
import n.ac.srmuniv.applicationcontextandroidclasses.ProductManagerApplication;
importin.ac.srmuniv.applicationcontextjavaclasses.ListProductModel;
importin.ac.srmuniv.applicationcontextactivities.R;
importandroid.app.Activity;
import android.os.Bundle;
import android.view.View;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.Toast;
public class AddProductActivity extends Activity {
   
    private EditText productNameEditText;
    private EditText productpriceEditText;
    private Button addButton;
    private Button cancelButton;

    privateProductManagerApplication globalVar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.add_product);
        globalVar=(ProductManagerApplication)getApplicationContext();
        productNameEditText = (EditText)findViewById(R.id.task_name);
        productpriceEditText = (EditText)findViewById(R.id.price);
        addButton = (Button)findViewById(R.id.add_button);
        cancelButton = (Button)findViewById(R.id.cancel_button);
       
        addButton.setOnClickListener(newView.OnClickListener() {
            public void onClick(View v) {
                addTask();
            }
        });
        cancelButton.setOnClickListener(newView.OnClickListener() {
            public void onClick(View v) {
                cancel();
            }
        });
    }

    protected void addTask() {
       
        String ProductName = productNameEditText.getText().toString();
        ListProductModel t = new ListProductModel();
        t.setProductName(ProductName);
        try {
            t.setprice(Double.parseDouble(productpriceEditText.getText().toString()));
            globalVar.addProduct(t);
           
            productNameEditText.setText("");
            productpriceEditText.setText("");
        } catch(NumberFormatException e) {
            Toast.makeText(getApplicationContext(),
                    "Product not added",
                            Toast.LENGTH_LONG)
                            .show();
            e.printStackTrace();
        }
   
    }

    protected void cancel() {
        finish();
    }

}
10.Copy the code  to the file strings.xml in res/values folder 
 <?xml version="1.0"encoding="utf-8"?>
<resources>

    <string name="app_name">SRM_ApplicationContextTutorial</string>
    <string name="action_settings">Settings</string>
    <string name="dialogbox_title">Product Deletion</string>
    <string name="dialogbox_message">Are you of Deleting product</string>
    <string name="dialogbox_deletebtn">Delete</string>
    <string name="addproduct_btn">Add Product</string>
    <string name="quitentry_btn">Quit</string>
    <string name="pricetotal_label">Total Price =</string>
    <string name="productname_label">Product Name</string>
    <string name="productprice_label">Product Price</string>
    
</resources>

11. Modify Androidmanifest.xml
<?xml version="1.0"
encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="in.ac.srmuniv.applicationcontextactivities"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:name="in.ac.srmuniv.applicationcontextandroidclasses.ProductManagerApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="in.ac.srmuniv.applicationcontextactivities.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name="in.ac.srmuniv.applicationcontextactivities.AddProductActivity">
        </activity>
    </application>

</manifest>
12.Run the application in the emulator. 

                
Figure 1 Shows Empty List View with products to be added Figure 2 shows when button is pressed AddProduct Activity being called  where price and product entries   are added  until Quit button pressed.


Figure 3 Shows the List of products added Figure 4 shows when an item is selected it calls Dialog box to ensure deletion of the product item.
Figure 5 Shows when an item is deleted..
CODE EXPLANATION
                                  MainActivity contains Custom List View which lists the product items to be added..Clicking "Add Product" button calls AddProductActivity which allows user to enter product name and price and clicking "Add Product" button in AddProductActivity adds the product in to ArrayList.ArrayList<ListProductmodel> productList which is used as global variable since it is an attribute of ProductManagerApplication classs.
The following code shows how to use how to use global variable across application in various android components such as Activities,Services etc for sharing data In our application declaration of Application object is done in MainActivity as well as AddProductActivity.
 private ProductManagerApplication globalVar;
Instantiation  of Application object is done in both Activities as shown below in onCreate() method
  globalVar=(ProductManagerApplication)getApplicationContext();

   Method calls on addProduct(),removeProducts(),calcProductTotal() in Application class through instance created in MainActivity and AddProduct Activity.They will share the common instance hence data can be shared.When Product is added in AddProduct Activity it is reflected in MainActivity ListView and Total price.
Purpose of Context is explained through Custom List adapter.Here we use custom adapter which extends BaseAdapter.Data source is ListProductModel.
getView
This is the method where listitem is binded to the ListView. Since we want to use our own list item, let's get the reference of our custom list item. To add any new layout to an existing layout, you need to inflate the other layout. To inflate a layout you need to get the reference of LayoutInflater. 
private static LayoutInflater inflater=null;
……..
/***********  Layout inflator to call external xmllayout () ***********/
        inflater = ( LayoutInflater )activity.
                getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 Context.LAYOUT_INFLATER_SERVICE. Getsystem service method is present in context. To get the reference of context, you can call this pointer on Activity,Here the MainActivity context is passed to this CustomAdapter class  in order to  serve the activity to fetch external xml resourse and inflate its listview
adapter=new CustomAdapter( this, CustomListViewValuesArr );
Once you have the layout inflater object, you just need to call inflate method on it.
vi = inflater.inflate(R.layout.product_row, null);
This inflates method takes 3 parameters, the layout which you want to add, the parent where the layout is being added , and third a boolean to attach the root to it's parent.
Through ViewHolder you can set the values of View elements in product_row.xml
holder = new ViewHolder();
            holder.text = (TextView) vi.findViewById(R.id.text);
            holder.text1=(TextView)vi.findViewById(R.id.text1);