Showing posts with label Android code sample: thread. Show all posts
Showing posts with label Android code sample: thread. Show all posts

Custom view to draw bitmap along path, calculate in background thread

Last post show a example of "Custom view to draw bitmap along path", with calculation run inside onDraw(). It's modified version to pre-calculate in back thread.


(remark: in last post, canvas.drawPath() is called inside onDraw(). It seem run very slow, removed in this example.)

Modify AnimationView.java
package com.blogspot.android_er.androidmovingbitmapalongpath;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

public class AnimationView extends View {

List<AnimationThing> animationThingsList;
public AnimationView(Context context) {
super(context);
initAnimationView();
}

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

public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAnimationView();
}

private void initAnimationView(){
animationThingsList = new ArrayList<>();
}

public void insertThing(AnimationThing thing){
animationThingsList.add(thing);
}

//prepare calculation in background thread
public void preDraw(){
for (AnimationThing thing : animationThingsList){
if(thing.distance < thing.pathLength){
thing.pathMeasure.getPosTan(thing.distance, thing.pos, thing.tan);

thing.matrix.reset();
float degrees = (float)(Math.atan2(thing.tan[1],
thing.tan[0])*180.0/Math.PI);
thing.matrix.postRotate(degrees, thing.bm_offsetX, thing.bm_offsetY);
thing.matrix.postTranslate(thing.pos[0]-thing.bm_offsetX,
thing.pos[1]-thing.bm_offsetY);

thing.distance += thing.step;
}else{
thing.distance = 0;
}
}
}

@Override
protected void onDraw(Canvas canvas) {
for (AnimationThing thing : animationThingsList){
canvas.drawBitmap(thing.bm, thing.matrix, null);
}

invalidate();
}


/*
@Override
protected void onDraw(Canvas canvas) {
for (AnimationThing thing : animationThingsList){

//This code run slow!!!
//canvas.drawPath(thing.animPath, thing.paint);

if(thing.distance < thing.pathLength){
thing.pathMeasure.getPosTan(thing.distance, thing.pos, thing.tan);

thing.matrix.reset();
float degrees = (float)(Math.atan2(thing.tan[1],
thing.tan[0])*180.0/Math.PI);
thing.matrix.postRotate(degrees, thing.bm_offsetX, thing.bm_offsetY);
thing.matrix.postTranslate(thing.pos[0]-thing.bm_offsetX,
thing.pos[1]-thing.bm_offsetY);

canvas.drawBitmap(thing.bm, thing.matrix, null);

thing.distance += thing.step;
}else{
thing.distance = 0;
}
}

invalidate();
}
*/



}


MainActivity.java
package com.blogspot.android_er.androidmovingbitmapalongpath;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Path;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

AnimationView myAnimationView;
AniThread myAniThread;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myAnimationView = (AnimationView)findViewById(R.id.MyAnimationView);

prepareThings();
myAniThread = new AniThread(myAnimationView);
myAniThread.start();

}

private void prepareThings() {
Path animPath;
float step;
Bitmap bm;

bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);

animPath = new Path();
animPath.moveTo(100, 100);
animPath.lineTo(200, 100);
animPath.lineTo(300, 50);
animPath.lineTo(400, 150);
animPath.lineTo(100, 300);
animPath.lineTo(600, 300);
animPath.lineTo(100, 100);
animPath.close();

step = 1;

AnimationThing thing = new AnimationThing(animPath, bm, step);
myAnimationView.insertThing(thing);

//The second thing
bm = BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_add);

animPath.reset();
animPath.addCircle(400, 400, 300, Path.Direction.CW);
step = 3;
thing = new AnimationThing(animPath, bm, step);
myAnimationView.insertThing(thing);
}

class AniThread extends Thread{

AnimationView targetView;

public AniThread(AnimationView target) {
super();
targetView = target;
}

@Override
public void run() {
while (true){
targetView.preDraw();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}


}


The other files, AnimationThing.java and activity_main.xml, refer last post.


download filesDownload the files .

Android example of using Thread and Handler


This example show how to run code in background using Thread, and also show passing data from activity to thread by calling method of thread, and passing data from thread to activity with Handler.


MainActivity.java
package com.blogspot.android_er.androidthread;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

Button btnStart, btnStop, btnSend;
EditText editTextMsgToSend;
TextView textViewCntReceived, textViewMsgReceived;

MyThread myThread;
MyHandler myHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = (Button)findViewById(R.id.startthread);
btnStop = (Button)findViewById(R.id.stopthread);
btnSend = (Button)findViewById(R.id.send);
editTextMsgToSend = (EditText)findViewById(R.id.msgtosend);
textViewCntReceived = (TextView)findViewById(R.id.cntreceived);
textViewMsgReceived = (TextView)findViewById(R.id.msgreceived);

myHandler = new MyHandler(this);

btnStart.setOnClickListener(btnStartOnClickListener);
btnStop.setOnClickListener(btnStopOnClickListener);
btnSend.setOnClickListener(btnSendOnClickListener);
}

View.OnClickListener btnStartOnClickListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
if(myThread != null){
myThread.setRunning(false);
}
myThread = new MyThread(myHandler);
myThread.start();
}
};

View.OnClickListener btnStopOnClickListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
if(myThread != null){
myThread.setRunning(false);
myThread = null;
}
}
};

View.OnClickListener btnSendOnClickListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
if(myThread != null){
myThread.msgToThread(editTextMsgToSend.getText().toString());
}
}
};

private void updateCnt(int cnt){
textViewCntReceived.setText(String.valueOf(cnt));
}

private void updateMsg(String msg){
textViewMsgReceived.setText(msg);
}


public static class MyHandler extends Handler{

public static final int UPDATE_CNT = 0;
public static final int UPDATE_MSG = 1;
private MainActivity parent;

public MyHandler(MainActivity parent) {
super();
this.parent = parent;
}

@Override
public void handleMessage(Message msg) {

switch (msg.what){
case UPDATE_CNT:
int c = (int)msg.obj;
parent.updateCnt(c);
break;
case UPDATE_MSG:
String m = (String)msg.obj;
parent.updateMsg(m);
break;
default:
super.handleMessage(msg);
}

}
}
}


MyThread.java
package com.blogspot.android_er.androidthread;

import android.os.Looper;
import android.os.Message;

public class MyThread extends Thread{

private int cnt;
private boolean running;
MainActivity.MyHandler mainHandler;

public MyThread(MainActivity.MyHandler mainHandler) {
super();
this.mainHandler = mainHandler;
}

public void setRunning(boolean running){
this.running = running;
}

public void msgToThread(String msgin){
String msgout = new StringBuilder(msgin).reverse().toString();
mainHandler.sendMessage(
Message.obtain(mainHandler,
MainActivity.MyHandler.UPDATE_MSG, msgout));
}

@Override
public void run() {
cnt = 0;
running = true;

String prompt;
if(Looper.myLooper() == Looper.getMainLooper()){
prompt = "myThread run in UI Thread";
}else{
prompt = "myThread run in NOT UI Thread";
}
mainHandler.sendMessage(
Message.obtain(mainHandler,
MainActivity.MyHandler.UPDATE_MSG, prompt));

while (running){
try {
Thread.sleep(1000);
mainHandler.sendMessage(
Message.obtain(mainHandler,
MainActivity.MyHandler.UPDATE_CNT, cnt));

cnt++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:padding="16dp"
android:orientation="vertical"
tools:context="com.blogspot.android_er.androidthread.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/startthread"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Thread"/>
<Button
android:id="@+id/stopthread"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop Thread"/>
<EditText
android:id="@+id/msgtosend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="msg to send..." />
<Button
android:id="@+id/send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send msg to thread"/>
<TextView
android:id="@+id/cntreceived"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="26dp"/>
<TextView
android:id="@+id/msgreceived"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textStyle="bold"
android:textSize="20dp"/>
</LinearLayout>



download filesDownload the files .

Related:
- Android example of using Service and BroadcastReceiver
- Example of IntentService and BroadcastReceiver

SwipeRefreshLayout, refresh in background thread


Last post show a basic example of SwipeRefreshLayout. But, normally refreshing involve some longtime task; such as loading data from Internet. This example show how to refresh with longtime task in background thread.


MainActivity.java
package com.blogspot.android_er.androidswiperefresh;

import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity {

SwipeRefreshLayout swipeRefreshLayout;
ListView swipeList;

List<String> myList;
ListAdapter adapter;

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

swipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.swiperefreshlayout);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
refresh();
}
});

swipeList = (ListView)findViewById(R.id.swipelist);

myList = new ArrayList<>();
adapter = new ArrayAdapter<String>(
this, android.R.layout.simple_list_item_1, myList);
swipeList.setAdapter(adapter);

swipeList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String item = (String) parent.getItemAtPosition(position);
Toast.makeText(MainActivity.this, item, Toast.LENGTH_LONG).show();
}
});
}

private void refresh(){

final int pos = myList.size();
myList.add(pos, "Refreshing...");
swipeList.invalidateViews();
swipeRefreshLayout.setRefreshing(true);

//refresh long-time task in background thread
new Thread(new Runnable() {
@Override
public void run() {
try {
//dummy delay for 2 second
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}

//update ui on UI thread
runOnUiThread(new Runnable() {
@Override
public void run() {
String currentDateTime =
DateFormat.getDateTimeInstance().format(new Date());
myList.set(pos, pos + " - " + currentDateTime);
swipeList.invalidateViews();
swipeRefreshLayout.setRefreshing(false);
}
});

}
}).start();
}
}


Keep using the layout in last post.

more:
- SwipeRefreshLayout, work with RecyclerView

Load something from Internet using URLConnection and ReadableByteChannel, in Thread

Last example show "Load something from Internet using URLConnection and BufferedReader, in Thread". Here is another example using java.nio.channels.ReadableByteChannel.

Read operations are synchronous on a ReadableByteChannel, that is, if a read is already in progress on the channel then subsequent reads will block until the first read completes. It is undefined whether non-read operations will block.


MainActivity.java
package com.blogspot.android_er.androidinternet;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class MainActivity extends AppCompatActivity {

TextView textResult;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textResult = (TextView)findViewById(R.id.tresult);

MyThread myThread = new MyThread("http://android-er.blogspot.com", textResult);
myThread.start();
}

class MyThread extends Thread{
String target;
TextView textviewResult;

private Handler handler = new Handler();

public MyThread(String target, TextView textviewResult) {
super();
this.target = target;
this.textviewResult = textviewResult;
}

@Override
public void run() {
String result = "";

URL url = null;
try {
url = new URL(target);
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();

ReadableByteChannel readableByteChannel = Channels.newChannel(inputStream);
ByteBuffer buffer = ByteBuffer.allocate(1024);

while (readableByteChannel.read(buffer) > 0)
{
result += new String(buffer.array());
buffer.clear();
}

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}


final String finalResult = result;
handler.post(new Runnable() {
@Override
public void run() {
textviewResult.setText(finalResult);
Toast.makeText(MainActivity.this,
"finished", Toast.LENGTH_LONG).show();
}
});
}
}
}


For layout and AndroidManifest.xml, refer to the previous post "Load something from Internet using URLConnection and BufferedReader, in AsyncTask".


Load something from Internet using URLConnection and BufferedReader, in Thread

Previous post show how to Load something from Internet using URLConnection and BufferedReader, in AsyncTask. This post show how to do it in Thread, and update UI using Handler.



MainActivity.java
package com.blogspot.android_er.androidinternet;

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class MainActivity extends AppCompatActivity {

TextView textResult;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textResult = (TextView)findViewById(R.id.tresult);

MyThread myThread = new MyThread("http://android-er.blogspot.com", textResult);
myThread.start();
}

class MyThread extends Thread{
String target;
TextView textviewResult;

private Handler handler = new Handler();

public MyThread(String target, TextView textviewResult) {
super();
this.target = target;
this.textviewResult = textviewResult;
}

@Override
public void run() {
String result = "";

try {
URL url = new URL(target);
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader inputStreamReader =
new InputStreamReader(inputStream);
BufferedReader buffReader = new BufferedReader(inputStreamReader);

String line;
while ((line = buffReader.readLine()) != null) {
result += line;
}

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

final String finalResult = result;
handler.post(new Runnable() {
@Override
public void run() {
textviewResult.setText(finalResult);
Toast.makeText(MainActivity.this,
"finished", Toast.LENGTH_LONG).show();
}
});
}
}
}


For layout and AndroidManifest.xml, refer to the previous post "Load something from Internet using URLConnection and BufferedReader, in AsyncTask".

Related:
- Load something from Internet using URLConnection and ReadableByteChannel, in Thread

AsyncTask vs Thread + Handler


This post show how to implement using AsyncTask and Thread/Handler to perform the same function: doing something in background and update UI elements (ProgressBar and TextView).

This video show how it run on Android Emulator running Android N, in Multi-Window.


AsyncTask

MainActivity.java
package com.blogspot.android_er.androidasynctask;

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

Button btnStart;
ProgressBar progressBar;
TextView textMsg;

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

progressBar = (ProgressBar)findViewById(R.id.progress);
textMsg = (TextView)findViewById(R.id.msg);

btnStart = (Button)findViewById(R.id.start);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyAsyncTask myAsyncTask = new MyAsyncTask(progressBar, textMsg);
myAsyncTask.execute();
}
});
}

class MyAsyncTask extends AsyncTask<Void, Integer, Void>{

ProgressBar pBar;
TextView tMsg;

public MyAsyncTask(ProgressBar pBar, TextView tMsg) {
super();
this.pBar = pBar;
this.tMsg = tMsg;
}

@Override
protected Void doInBackground(Void... params) {
for(int i=0; i<=10; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

publishProgress(i);
}
return null;
}

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

@Override
protected void onPostExecute(Void aVoid) {
tMsg.setText("finished");
}
}
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:padding="16dp"
android:orientation="vertical"
tools:context="com.blogspot.android_er.androidasynctask.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

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

<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:indeterminate="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progress="0"/>
<TextView
android:id="@+id/msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>



Thread + Handler

MainActivity.java
package com.blogspot.android_er.androidthreadhandler;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import org.w3c.dom.Text;

public class MainActivity extends AppCompatActivity {

Button btnStart;
ProgressBar progressBar;
TextView textMsg;

private Handler handler = new Handler();

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

progressBar = (ProgressBar)findViewById(R.id.progress);
textMsg = (TextView)findViewById(R.id.msg);

btnStart = (Button)findViewById(R.id.start);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyThread myThread = new MyThread(progressBar, textMsg);
myThread.start();
}
});
}

class MyThread extends Thread{

ProgressBar pBar;
TextView tMsg;

public MyThread(ProgressBar pBar, TextView tMsg) {
super();
this.pBar = pBar;
this.tMsg = tMsg;
}

@Override
public void run() {

for (int i = 0; i <= 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

//is accessed from within inner class, needs to be declared final
final int finalI = i;
handler.post(new Runnable() {
@Override
public void run() {
pBar.setProgress(finalI);
}
});
}

handler.post(new Runnable() {
@Override
public void run() {
tMsg.setText("finished");
}
});
}
}
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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:padding="16dp"
android:orientation="vertical"
tools:context="com.blogspot.android_er.androidthreadhandler.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />

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

<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:indeterminate="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progress="0"/>
<TextView
android:id="@+id/msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>



next:
- HandlerThread example

related:
- Load something from Internet using URLConnection and BufferedReader, in AsyncTask
- Load something from Internet using URLConnection and BufferedReader, in Thread


GridView example: load images to GridView from SD Card in background

Recall from the "old exercise of GridView", loading images to GridView from SD Card in onCreate() method running in main thread. Actually, it may take long time to finish, so it should be moved to background thread. This exercise move the file loading operation to AsyncTask running in background thread.

Also introduce Reload button to demonstrate how to clear and reload the list.

Load images to GridView from SD Card


Here are some notes in my implementation:
  • In my trial experience, should not access ImageAdapter(extends BaseAdapter) from background thread such as doInBackground(). Doing so will conflict with ImageAdapter's getView() method, and generate IndexOutOfBoundsException occasionally. It whould be accessed in UI thread, so the clear(), add() and notifyDataSetChanged() have been moved to onPreExecute(), onProgressUpdate() and onPostExecute().
  • Cancel the AsyncTask if not need.
  • In my approach, always new another ImageAdapter when reloading; to prevent the list inside mixed with a invalid but still running AsyncTask.

package com.example.androidgridview;

import java.io.File;
import java.util.ArrayList;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

AsyncTaskLoadFiles myAsyncTaskLoadFiles;

public class AsyncTaskLoadFiles extends AsyncTask<Void, String, Void> {

File targetDirector;
ImageAdapter myTaskAdapter;

public AsyncTaskLoadFiles(ImageAdapter adapter) {
myTaskAdapter = adapter;
}

@Override
protected void onPreExecute() {
String ExternalStorageDirectoryPath = Environment
.getExternalStorageDirectory().getAbsolutePath();

String targetPath = ExternalStorageDirectoryPath + "/test/";
targetDirector = new File(targetPath);
myTaskAdapter.clear();

super.onPreExecute();
}

@Override
protected Void doInBackground(Void... params) {

File[] files = targetDirector.listFiles();
for (File file : files) {
publishProgress(file.getAbsolutePath());
if (isCancelled()) break;
}
return null;
}

@Override
protected void onProgressUpdate(String... values) {
myTaskAdapter.add(values[0]);
super.onProgressUpdate(values);
}

@Override
protected void onPostExecute(Void result) {
myTaskAdapter.notifyDataSetChanged();
super.onPostExecute(result);
}

}

public class ImageAdapter extends BaseAdapter {

private Context mContext;
ArrayList<String> itemList = new ArrayList<String>();

public ImageAdapter(Context c) {
mContext = c;
}

void add(String path) {
itemList.add(path);
}

void clear() {
itemList.clear();
}

void remove(int index){
itemList.remove(index);
}

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

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return itemList.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) { // if it's not recycled, initialize some
// attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(220, 220));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
} else {
imageView = (ImageView) convertView;
}

Bitmap bm = decodeSampledBitmapFromUri(itemList.get(position), 220,
220);

imageView.setImageBitmap(bm);
return imageView;
}

public Bitmap decodeSampledBitmapFromUri(String path, int reqWidth,
int reqHeight) {

Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);

// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);

// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(path, options);

return bm;
}

public int calculateInSampleSize(

BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float) height
/ (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}

return inSampleSize;
}

}

ImageAdapter myImageAdapter;

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

final GridView gridview = (GridView) findViewById(R.id.gridview);
myImageAdapter = new ImageAdapter(this);
gridview.setAdapter(myImageAdapter);

/*
* Move to asyncTaskLoadFiles String ExternalStorageDirectoryPath =
* Environment .getExternalStorageDirectory() .getAbsolutePath();
*
* String targetPath = ExternalStorageDirectoryPath + "/test/";
*
* Toast.makeText(getApplicationContext(), targetPath,
* Toast.LENGTH_LONG).show(); File targetDirector = new
* File(targetPath);
*
* File[] files = targetDirector.listFiles(); for (File file : files){
* myImageAdapter.add(file.getAbsolutePath()); }
*/
myAsyncTaskLoadFiles = new AsyncTaskLoadFiles(myImageAdapter);
myAsyncTaskLoadFiles.execute();

gridview.setOnItemClickListener(myOnItemClickListener);

Button buttonReload = (Button)findViewById(R.id.reload);
buttonReload.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {

//Cancel the previous running task, if exist.
myAsyncTaskLoadFiles.cancel(true);

//new another ImageAdapter, to prevent the adapter have
//mixed files
myImageAdapter = new ImageAdapter(MainActivity.this);
gridview.setAdapter(myImageAdapter);
myAsyncTaskLoadFiles = new AsyncTaskLoadFiles(myImageAdapter);
myAsyncTaskLoadFiles.execute();
}});

}

OnItemClickListener myOnItemClickListener = new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String prompt = "remove " + (String) parent.getItemAtPosition(position);
Toast.makeText(getApplicationContext(), prompt, Toast.LENGTH_SHORT)
.show();

myImageAdapter.remove(position);
myImageAdapter.notifyDataSetChanged();

}
};

}


<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">

<Button
android:id="@+id/reload"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reload"/>
<GridView
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"/>

</LinearLayout>


download filesDownload the files.

download filesDownload and try the APK.



Next:
- getView() to load images in AsyncTask