Android Pull Down to Refresh And Release to Update (Part 2 , PHP & MySQL) |
Android Pull Down to Refresh And Release to Update (Part 2 , PHP & MySQL) บทความ Android นี้เป็นภาคต่อของ Pull to refresh (Part 1) (เพื่อความเข้าใจ ควรอ่านบทความนี้ก่อน) และตัวอย่างนี้จะเป็นการ Apply เทคนิค Pull down to refresh กับข้อมูลจริง โดยใช้การดึงข้อมูลจาก Web Server (Website) ที่ทำงานด้วย PHP กับ MySQL และใช้เทคนิคการรับ-ส่งข้อมุลผ่าน JSON พร้อม ๆ กับใช้ ListView ของ Android ในการแสดงผลข้อมลเหล่านั้น
Pull down to refresh and PHP & MySQL (Website)
Concept การทำงานคือจะสร้าง PHP กับ MySQL และเก็บไว้บน Web Server และใช้ Android เรียกข้อมูลจาก URL ของเว็บไซต์ผ่าน HttpGet ซึ่งจะได้ข้อมูลกลับมาในรูปแบบของ JSON และ Android จะนำข้อมูลเหล่านั้นมาสร้าง Adapter เพื่อแสดงข้อมูลบน ListView
และใช้เทคนิค Pull down to refresh พร้อม ๆ กับการไปดึงข้อมูลจาก Web Server มาอีกครั้ง
Web Server (PHP & MySQL)
images
CREATE TABLE `images` (
`ImageID` int(11) NOT NULL auto_increment,
`ImageName` varchar(50) NOT NULL,
`ImagePath_Thumbnail` varchar(150) NOT NULL,
`ImagePath_FullPhoto` varchar(150) NOT NULL,
`Rating` float NOT NULL,
PRIMARY KEY (`ImageID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
--
-- Dumping data for table `images`
--
INSERT INTO `images` VALUES (1, 'Image 1', 'https://www.thaicreate.com/android/img1_thum.jpg', 'https://www.thaicreate.com/android/img1_full.jpg', 0);
INSERT INTO `images` VALUES (2, 'Image 2', 'https://www.thaicreate.com/android/img2_thum.jpg', 'https://www.thaicreate.com/android/img2_full.jpg', 0);
INSERT INTO `images` VALUES (3, 'Image 3', 'https://www.thaicreate.com/android/img3_thum.jpg', 'https://www.thaicreate.com/android/img3_full.jpg', 0);
INSERT INTO `images` VALUES (4, 'Image 4', 'https://www.thaicreate.com/android/img4_thum.jpg', 'https://www.thaicreate.com/android/img4_full.jpg', 0);
INSERT INTO `images` VALUES (5, 'Image 5', 'https://www.thaicreate.com/android/img5_thum.jpg', 'https://www.thaicreate.com/android/img5_full.jpg', 0);
INSERT INTO `images` VALUES (6, 'Image 6', 'https://www.thaicreate.com/android/img6_thum.jpg', 'https://www.thaicreate.com/android/img6_full.jpg', 0);
โครงสร้างของ MySQL Database

getGallery.php
<?php
$objConnect = mysql_connect("localhost","root","root");
$objDB = mysql_select_db("mydatabase");
$strSQL = "SELECT * FROM images WHERE 1 ";
$objQuery = mysql_query($strSQL);
$intNumField = mysql_num_fields($objQuery);
$resultArray = array();
while($obResult = mysql_fetch_array($objQuery))
{
$arrCol = array();
for($i=0;$i<$intNumField;$i++)
{
$arrCol[mysql_field_name($objQuery,$i)] = $obResult[$i];
}
array_push($resultArray,$arrCol);
}
mysql_close($objConnect);
echo json_encode($resultArray);
?>
ไฟล์ php ที่ทำหน้าอ่านข้อมูลจาก MySQL และส่งค่ากลับไปยัง Android ในรูปแบบของ JSON

Android Project
โครงสร้างของไฟล์

ประกอบด้วย 3 ไฟล์ คือ MainActivity.java , activity_main.xml และ activity_column.xml
และเพื่อความเข้าใจควรอ่านจาก Pull to refresh (Part 1) เสียก่อน
activity_main.xml

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Pull Refresh : "
android:layout_span="1"
android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/txtUpdateTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Update Time" />
</TableRow>
<View
android:layout_height="1dip"
android:background="#CCCCCC" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.1">
<com.markupartist.android.widget.PullToRefreshListView
android:id="@+id/pull_to_refresh_listview"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:background="@android:color/white"
android:cacheColorHint="@android:color/white" />
</LinearLayout>
<View
android:layout_height="1dip"
android:background="#CCCCCC" />
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="By.. ThaiCreate.Com" />
</LinearLayout>
</TableLayout>
activity_column.xml

<TableLayout android:id="@+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/ColImgPath"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/ColImgID"
android:text="Column 1" />
<TextView
android:id="@+id/ColImgName"
android:text="Column 2" />
</TableRow>
</TableLayout>
MainActivity.java
package com.myapp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.markupartist.android.widget.PullToRefreshListView;
import com.markupartist.android.widget.PullToRefreshListView.OnRefreshListener;
public class MainActivity extends Activity {
private PullToRefreshListView listView;
ArrayList<HashMap<String, Object>> MyArrList;
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_main);
setProgressBarIndeterminateVisibility(false);
// Permission StrictMode
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
listView = (PullToRefreshListView) findViewById(R.id.pull_to_refresh_listview);
// Where refresh
listView.setOnRefreshListener(new OnRefreshListener() {
public void onRefresh() {
new DownloadJSONFileAsync().execute();
}
});
// Download first time
new DownloadJSONFileAsync().execute();
}
// Show All Content
public void ShowAllContent()
{
// listView1
listView.setAdapter(new ImageAdapter(MainActivity.this,MyArrList));
}
public class ImageAdapter extends BaseAdapter
{
private Context context;
private ArrayList<HashMap<String, Object>> MyArr = new ArrayList<HashMap<String, Object>>();
public ImageAdapter(Context c, ArrayList<HashMap<String, Object>> myArrList)
{
// TODO Auto-generated method stub
context = c;
MyArr = myArrList;
}
public int getCount() {
// TODO Auto-generated method stub
return MyArr.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = inflater.inflate(R.layout.activity_column, null);
}
// ColImage
ImageView imageView = (ImageView) convertView.findViewById(R.id.ColImgPath);
imageView.getLayoutParams().height = 110;
imageView.getLayoutParams().width = 80;
imageView.setPadding(10, 10, 10, 10);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
try
{
imageView.setImageBitmap((Bitmap)MyArr.get(position).get("ImageThumBitmap"));
} catch (Exception e) {
// When Error
imageView.setImageResource(android.R.drawable.ic_menu_report_image);
}
// Click on Image
imageView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
/*
String strImageID = MyArr.get(position).get("ImageID").toString();
String strImageName = MyArr.get(position).get("ImageName").toString();
String strImagePathFull = MyArr.get(position).get("ImagePathFull").toString();
Intent newActivity = new Intent(MainActivity.this,VoteActivity.class);
newActivity.putExtra("ImageID", strImageID);
newActivity.putExtra("ImageName", strImageName);
newActivity.putExtra("ImagePathFull", strImagePathFull);
startActivity(newActivity);
*/
}
});
// ColImgID
TextView txtImgID = (TextView) convertView.findViewById(R.id.ColImgID);
txtImgID.setPadding(5, 0, 0, 0);
txtImgID.setText("ID : " + MyArr.get(position).get("ImageID").toString());
// ColImgName
TextView txtPicName = (TextView) convertView.findViewById(R.id.ColImgName);
txtPicName.setPadding(5, 0, 0, 0);
txtPicName.setText("Name : " + MyArr.get(position).get("ImageName").toString());
return convertView;
}
}
// Download JSON in Background
public class DownloadJSONFileAsync extends AsyncTask<String, Void, Void> {
protected void onPreExecute() {
super.onPreExecute();
setProgressBarIndeterminateVisibility(true);
}
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
String url = "https://www.thaicreate.com/android/getGallery.php";
JSONArray data;
try {
data = new JSONArray(getJSONUrl(url));
MyArrList = new ArrayList<HashMap<String, Object>>();
HashMap<String, Object> map;
for(int i = 0; i < data.length(); i++){
JSONObject c = data.getJSONObject(i);
map = new HashMap<String, Object>();
map.put("ImageID", (String)c.getString("ImageID"));
map.put("ImageName", (String)c.getString("ImageName"));
// Thumbnail Get ImageBitmap To Object
map.put("ImagePathThum", (String)c.getString("ImagePath_Thumbnail"));
map.put("ImageThumBitmap", (Bitmap)loadBitmap(c.getString("ImagePath_Thumbnail")));
// Full (for View Popup)
map.put("ImagePathFull", (String)c.getString("ImagePath_FullPhoto"));
map.put("Rating", (String)c.getString("Rating"));
MyArrList.add(map);
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void unused) {
ShowAllContent(); // When Finish Show Content
listView.onRefreshComplete();
setProgressBarIndeterminateVisibility(false);
//Update Time..
// Current Date
Calendar c = Calendar.getInstance();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = df.format(c.getTime());
TextView updateTime = (TextView) findViewById(R.id.txtUpdateTime);
updateTime.setText("Update : " + formattedDate);
}
}
/*** Get JSON Code from URL ***/
public String getJSONUrl(String url) {
StringBuilder str = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) { // Download OK
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
str.append(line);
}
} else {
Log.e("Log", "Failed to download file..");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return str.toString();
}
/***** Get Image Resource from URL (Start) *****/
private static final String TAG = "Image";
private static final int IO_BUFFER_SIZE = 4 * 1024;
public static Bitmap loadBitmap(String url) {
Bitmap bitmap = null;
InputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new URL(url).openStream(), IO_BUFFER_SIZE);
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);
copy(in, out);
out.flush();
final byte[] data = dataStream.toByteArray();
BitmapFactory.Options options = new BitmapFactory.Options();
//options.inSampleSize = 1;
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,options);
} catch (IOException e) {
Log.e(TAG, "Could not load Bitmap from: " + url);
} finally {
closeStream(in);
closeStream(out);
}
return bitmap;
}
private static void closeStream(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
android.util.Log.e(TAG, "Could not close stream", e);
}
}
}
private static void copy(InputStream in, OutputStream out) throws IOException {
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
while ((read = in.read(b)) != -1) {
out.write(b, 0, read);
}
}
/***** Get Image Resource from URL (End) *****/
}
Screenshot ทดสอบผ่าน Emulator

กำลังโหลดข้อมูล ซึ่งจะแสดง ProgressBar แบบ Indeterminate

แสดงข้อมูลซึ่งจะระบุเวลาที่ Update

ข้อมูลทั้งหมดจะดึงมาจาก Web Server ที่เป็น PHP กับ MySQL

ทดสอบการแก้ไขข้อมูลใน phpMyAdmin ของ MySQL

แล้วทดสอบ Pull to refresh เพื่อดูว่ารายการจะ Update หรือไม่

ปล่อย Release to refresh

หลังจากปล่อยจะแสดง ProgressBar แบบ Indeterminate และในส่วนของ Full to refresh ก็แสดง Loading...

หลังจากโหลดเรียบร้อยแล้วก็จะเห็นว่าข้อมูลใน ListView จะ Update ตามข้อมูลจาก Web Server
สำหรับ Code ทั้งหมดสามารถดาวน์โหลดได้จากส่วนท้ายของบทความ
.
|
ช่วยกันสนับสนุนรักษาเว็บไซต์ความรู้แห่งนี้ไว้ด้วยการสนับสนุน Source Code 2.0 ของทีมงานไทยครีเอท
|
|
|
By : |
ThaiCreate.Com Team (บทความเป็นลิขสิทธิ์ของเว็บไทยครีเอทห้ามนำเผยแพร่ ณ เว็บไซต์อื่น ๆ) |
|
Score Rating : |
  |
|
|
Create/Update Date : |
2012-09-08 12:42:19 /
2017-03-26 22:33:44 |
|
Download : |
|
|
Sponsored Links / Related |
|
|
|
|
|
|
|