Android GridView on Home Page with auto resized images.

When looking for a way to get a grid view with images like the above, my final result is something I want with icons and an image to depict a task.

I had to follow the below steps:

  1. Create a main fragment and add your grid view to it.
  2. Define a grid view item with an image and a text on its footer.
  3. Add an Adapter to the GridView for it to be compatible.
  4. Add the GridView adapter to the Main Fragment.

In you home fragment, for example ‘fragment_main.xml’ 

<FrameLayout 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: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.nomoreboundary.propertymanagerpro.MainActivity.MainFragment"
    android:id="@+id/frameLayout_main">

    <GridView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/gridView_main"
        android:layout_centerHorizontal="true"
        android:layout_alignParentTop="true"
        android:verticalSpacing="5dp"
        android:horizontalSpacing="5dp"
        android:stretchMode="columnWidth"
        android:numColumns="2"
        android:smoothScrollbar="true" />

</FrameLayout>

We will create a new layout for an image that is to be shown on a grid.  Let say it includes and image and a text on its footer.

grid_image.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.nomoreboundary.propertymanagerpro.util.GridImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/footer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom" />

</FrameLayout>

 

Image View class with overridable sizing

GridImageView.java

public class GridImageView extends ImageView {

    public GridImageView(Context context) {
        super(context);
    }

    public GridImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public GridImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); 
    }

}

 

An adapter for showing the grid view

MainGridAdapter.java

class MainGridAdapter extends BaseAdapter {

        private List<Item> items = new ArrayList<>();
        private LayoutInflater inflater;

        public MainGridAdapter(Context context)
        {
            inflater = LayoutInflater.from(context);

            items.add(new Item("Image 1", R.drawable.bk_beach));
            items.add(new Item("Image 2", R.drawable.bk_bluecoffee));
            items.add(new Item("Image 3", R.drawable.bk_purple_yellow));
            items.add(new Item("Image 4", R.drawable.bk_railroad));
            items.add(new Item("Image 5", R.drawable.bk_lines));
        }

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

        @Override
        public Object getItem(int i)
        {
            return items.get(i);
        }

        @Override
        public long getItemId(int i)
        {
            return items.get(i).drawableId;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup)
        {
            View v = view;
            ImageView picture;
            TextView name;

            if(v == null)
            {
                v = inflater.inflate(R.layout.grid_main, viewGroup, false);
                v.setTag(R.id.picture, v.findViewById(R.id.picture));
                v.setTag(R.id.text, v.findViewById(R.id.text));
            }

            picture = (ImageView)v.getTag(R.id.picture);
            name = (TextView)v.getTag(R.id.text);

            Item item = (Item)getItem(i);

            picture.setImageResource(item.drawableId);
            name.setText(item.name);

            return v;
        }

        private class Item
        {
            final String name;
            final int drawableId;

            Item(String name, int drawableId)
            {
                this.name = name;
                this.drawableId = drawableId;
            }
        }
}

 

Add the grid adapter to the Main Fragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
	View rootView = inflater.inflate(R.layout.fragment_main, container, false);

	// Set up the grid view.
	GridView gridView = (GridView) rootView.findViewById(R.id.gridView_main);
	gridView.setAdapter(new MainGridAdapter(getActivity()));

	return rootView;
}
Advertisements

Android NDK Interview Questions

General


 

1. What is Android NDK?

Native development Kit as it it called gives you ace

2.  When can the callback implementations to NativeActivity cause an ANR?

Native activity contains all the callback information and data structures.  The main thread handles the callbacks.  So, your callback implementations should not be blocking.  If they block, you may receive an ANR because your main thread is unresponsive until the callback returns.

3.

Android Interview questions

Threads


 1.  During Android unit testing, what is the difficulty in using ‘static’ variables?

Static variables are cleared and set to ‘null’ each time a set of data is called.  This is because your app is reset/killed each time

Solution:  Call super.tearDown() before each test.

2.   What is dependency injection in Android?

Dependency injection is a style of object configuration in which an objects fields and collaborators are set by an external entity.

In Android, Dagger & Guice are examples of dependency injectors:

RoboGuice 2 example:

    @ContentView(R.layout.main)
    class RoboWay extends RoboActivity { 
        @InjectView(R.id.name)             TextView name; 
        @InjectView(R.id.thumbnail)        ImageView thumbnail; 
        @InjectResource(R.drawable.icon)   Drawable icon; 
        @InjectResource(R.string.app_name) String myName; 
        @Inject                            LocationManager loc; 

        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            name.setText( "Hello, " + myName ); 
        } 
    }

 

3.  How is Serializable different from Parcel?

Parcels are designed for high performance IPC transport, used heavily in Binders.  For normal serialization concepts, use Serializable.  Serializable is much heavier and takes more time.  Therefore Parcels are used in embedded devices.

4.   What is a Handler, Thread & Loader?

Handler:  A class that can synchronize a worker thread to the main thread.  In the example of ASyncTask, the onProgressUpdate() and the doPostExecute() method are already synchronized.  They are examples of handlers.  You can create your custom handler methods for your custom thread classes.

Thread:  A line of execution.

Loader:

  • It provides asynchronous loading of data.
  • They are available to every Activity and Fragment.
  •  They monitor the data source and deliver new results when contents change.
  • They automatically reload to their last loader cursor when being recreated after a configuration change.  They don’t need to re-query data

5.  What is a looper, message queue and handler?

Looper – part of any Thread to loop through message queue.  This will be used to check if any incoming message has arrived to this thread. Only one looper exists for a given thread. Only for handler threads this looper will be activated, for other normal threads this will be in passive or inactive mode.

Message Queue – part of any thread, will store incoming messages to this thread. For any thread only one message Q is available. Handler – communication channel between two threads.

Handler is associated with Looper. for a given looper we can n number of handlers to communicate with it from out side world.

Memory Leaks


 1.  What are some of the causes for memory leaks in Android?

Leaking a context causes references to an Activity’s view group and all its resources inside it.

2.  What is the most common memory leak in Android?

Screen orientation change.  When this happens,  Android destroys the current activity and creates a new one  preserving its state.   This can cause a leak in the entire Activity and all its references resources.

3.  What is a leak?

Keeping a reference to any object that the garbage collector is unable to collect.

4.  How to avoid Context related leaks?

  • Avoid using non-static inner classes in an activity if instances of the inner class could outlive the activity’s lifecycle. Instead, prefer static inner classes and hold a weak reference to the activity inside.

5. How can you leak a Context?

In Java, non-static inner and anonymous classes hold an implicit reference to their outer class. Static inner classes, on the other hand, do not.

Views


 1.  How do you create a View programmatically without using a View  Inflater service?

LinearLayout myLayout = findViewById(R.id.main);

Button myButton = new Button(this);
myButton.setLayoutParams(new LinearLayout.LayoutParams(
                          LinearLayout.LayoutParams.FILL_PARENT,
                          LinearLayout.LayoutParams.FILL_PARENT));

myLayout.addView(myButton);

Context


 1. What are contexts used for?

Various reasons but mostly to load and access resources.  This is why all widgets have a context parameter.

2.  What are some types of Contexts?

Application Context

An instance of Context that is tied to the lifecycle of the application.

Example:  Use when you need something that is tied to a global scope.  Such as a WakefulIntentService.  To get a static WakeLock you would need a context to PowerManager.  In this case it is safest to use getApplicationContext().

Activity context

An instance of Context that is tied to the lifecycle of an activity.

Usually passed to classes and methods that require a context.   Holds a reference to a Viewgroup and all the resources inside it.   If a context leaks, the entire activity can be leaked since a reference is always held causing a lot of memory to be held up.

Services


1.  What is a started Service?

When this service is started, it has a lifecycle that’s independent of the component that started it and the service can run in the background indefinitely, even if the component that started it is destroyed. As such, the service should stop itself when its job is done by calling stopSelf() or another component can stop it by calling stopService()

2.  What is a bound Service?

You should create a bound service when you want to interact with the service from activities and other components in your application or to expose some of your application’s functionality to other applications, through interprocess communication (IPC).

Application Questions


 1. Photo Sharing App / notification manager attach to a notification object, what would you use

Pending Intent

2. Data from one app to another and if you want some fields hidden

Content Provider

3. If your app has to have messaging as an option, what would you use to navigate to the messaging app.

 

4.  If you want an animation to appear .5 sec after a button click, what would you use?

 

5. Android Service – Does it run on UI thread?

Yes

6.  How do you schedule a recurring task at periodic intervals

Alarm Manager

My Rental Pro

Today’s Featured App

My Rental Pro

mrp_feature_graphic

Ever found the need to manage you rental property the way you want it to be.  An intuitive app that tracks and shows what you need and watch your cash flow grow.

You can use the app to manage all your rental properties, collect rents, track expenses.  If your property has a mortgage on it, the app provides parameters to see how your rents calculate against your existing loan.   The best part of the app is visualizing cash-flow against all values of your property and see how it is doing.

You can also hypothetically model a property and see if it will make money starting this year.

Get it on Google Play

My Rental Pro

Today’s Featured App

My Rental Pro

mrp_feature_graphic

Ever found the need to manage you rental property the way you want it to be.  An intuitive app that tracks and shows what you need and watch your cash flow grow.

You can use the app to manage all your rental properties, collect rents, track expenses.  If your property has a mortgage on it, the app provides parameters to see how your rents calculate against your existing loan.   The best part of the app is visualizing cash-flow against all values of your property and see how it is doing.

You can also hypothetically model a property and see if it will make money starting this year.

Get it on Google Play

Android – Handler, Message Queue and Loopers

Looper – part of any Thread to loop through message queue. This will be used to check if any incoming message has arrived to this thread. Only one looper exists for a given thread. Only for handler threads this looper will be activated, for other normal threads this will be in passive or inactive mode.

Message Queue – part of any thread, will store incoming messages to this thread. For any thread only one message Q is available. Handler – communication channel between two threads.

Handler is associated with Looper. for a given looper we can n number of handlers to communicate with it from out side world.

Create a Dialog box using DialogFragment in Android

Say you want to create a dialog box that lets you remove an item from a list, or some other similar activity.

1.  Create a DialogFragment class

public class DeleteItemDialogFragment extends DialogFragment {

    @Override

    public Dialog onCreateDialog(Bundle savedInstanceState) {

        // Use the Builder class for convenient dialog construction

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(R.string.remove_rent) .setPositiveButton(R.string.remove, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) {

                   // Send the positive button event back to the host activity

                   mListener.onDialogPositiveClick(DeleteItemDialogFragment.this); } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) {

                   // Send the negative button event back to the host activity

                   mListener.onDialogNegativeClick(DeleteItemDialogFragment.this); } });

        // Create the AlertDialog object and return it

        return builder.create(); }

    /* The activity that creates an instance of this dialog fragment must

 

     * implement this interface in order to receive event callbacks.

 

     * Each method passes the DialogFragment in case the host needs to query it. */

public interface DeleteItemDialogListener { public void onDialogPositiveClick(DialogFragment dialog); public void onDialogNegativeClick(DialogFragment dialog); } DeleteItemDialogListener mListener;

    // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener

 

    @Override

    public void onAttach(Activity activity) { super.onAttach(activity);

        // Verify that the host activity implements the callback interface

        try {

            // Instantiate the DeleteItemDialogListener so we can send events to the host

            mListener = (DeleteItemDialogListener) activity; } catch (ClassCastException e) {

            // The activity doesn’t implement the interface, throw exception

            throw new ClassCastException(activity.toString()

                    + ” must implement DeleteItemDialogListener”);

        } } }

2.   Set up your listener in your activity:

public class ManageRentActivity extends FragmentActivity implements DeleteItemDialogFragment.DeleteItemDialogListener {
}

3.   Use the implemented methods to set up the ‘Confirm’ and ‘Cancel’ methods:

@Override
public void onDialogPositiveClick(DialogFragment dialog) {  
         //removeRentEntry();  }
@Override 
public void onDialogNegativeClick(DialogFragment dialog) { 
         // Cancel and Return to Activity }

3. Call your DialogFragment from your Activity:

DialogFragment removeDialogFragment = new DeleteItemDialogFragment();
removeDialogFragment.show(getSupportFragmentManager(),  "DeleteItemDialogFragment");

Android SQLite database – A tutorial

1.   Create the DatabaseHelper class. This class is responsible for creating the database. The onUpgrade() method will simply delete all existing data and re-create the table. It also defines several constants for the table name and the table columns.

public class DatabaseHelper extends SQLiteOpenHelper {

	  private static final String DATABASE_NAME = "property.db";
	  private static final int DATABASE_VERSION = 1;
	  
	  public static final String TABLE_PROPERTY = "property";
	  public static final String COLUMN_ID = "_id";
	  public static final String COLUMN_NICKNAME = "nickname";
	  public static final String COLUMN_TENANT = "tenant";
	  public static final String COLUMN_ADDRESS = "address";
	  public static final String COLUMN_LOAN = "loan";

	  // Database creation sql statement
	  private static final String DATABASE_CREATE = "create table "
	      + TABLE_PROPERTY + "(" + COLUMN_ID
	      + " integer primary key autoincrement, " 
	      + COLUMN_NICKNAME + " text not null"
	      + COLUMN_TENANT + " text"
	      + COLUMN_ADDRESS + " address not null"
	      + COLUMN_LOAN + " integer);";

	  public DatabaseHelper(Context context) {
	    super(context, DATABASE_NAME, null, DATABASE_VERSION);
	  }

	  @Override
	  public void onCreate(SQLiteDatabase database) {
	    database.execSQL(DATABASE_CREATE);
	  }

	  @Override
	  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	    Log.w(DatabaseHelper.class.getName(),
	        "Upgrading database from version " + oldVersion + " to "
	            + newVersion + ", which will destroy all old data");
	    db.execSQL("DROP TABLE IF EXISTS " + TABLE_PROPERTY);
	    onCreate(db);
	  }

	}