First, I implement this function in a way that is easy to understand.
On the server side, create an index. php file to read MySQL database information:
Index. php:
<? Php
$ Link = mysql_connect ("localhost", "root", "123456 ");
Mysql_query ("set names utf8 ");
Mysql_select_db ("test", $ link); // test indicates the database name.
$ SQL = mysql_query ("select * from interp_images", $ link); // interp_images indicates the table name.
While ($ row = mysql_fetch_assoc ($ SQL ))
$ Output [] = $ row;
Print (json_encode ($ output ));
Mysql_close ();
?>
This PHP file is executed to obtain the array of data read from the database table.
The main code of the program is described as follows:
Listviewdomainmaceactivity. java:
Public class listviewdomainmaceactivity extends Activity {
Protected static final String TAG = "listview1_maceactivity ";
/** Called when the activity is first created .*/
Private ListView mListview;
ImageLoader mImageLoader = new ImageLoader ();
MyAdapter adapter;
Private JSONArray jArray;
Private String result = null;
Private InputStream is = null;
Private StringBuilder sb = null;
// Private ListView mListView;
Private View mView;
Private String imageUrl;
Private String imageDetailUrl;
Private int ct_id;
Private String ct_name;
Private String ct_detail_name;
Private JSONObject json_data = null;
Private String [] fileUrl;
Private String [] detailUrl;
Private int count;
Private Bitmap bitmap;
Private byte buff [] = new byte [1024*250];
@ Override
Public void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. main );
// TODO http get
Try {
HttpClient httpclient = new DefaultHttpClient ();
HttpGet httpget = new HttpGet ("http: // 192.168.18.29/Test/index. php "); // the IP address is the IP address of your server. Because the mobile phone is connected to the lan wifi, you can test the effect by using only your computer as the server.
HttpResponse response = httpclient.exe cute (httpget );
HttpEntity entity = response. getEntity ();
Is = entity. getContent ();
} Catch (Exception e ){
Log. e ("log_tag", "2013 Error in http connection" + e. toString ());
}
// Convert response to string
Try {
BufferedReader reader = new BufferedReader (new InputStreamReader (is, "iso-8859-1"), 8 );
Sb = new StringBuilder ();
Sb. append (reader. readLine () + "\ n ");
String line = "0 ";
While (line = reader. readLine ())! = Null ){
Sb. append (line + "\ n ");
}
Is. close ();
Result = sb. toString ();
} Catch (Exception e ){
E. printStackTrace ();
Log. e ("log_tag", "Error converting result" + e. toString ());
}
//////////////////////////////////////// ///////////////////////////////////////
// Paring data
Try {
JArray = new JSONArray (result );
// JSONObject json_data = null;
Count = 0;
DetailUrl = new String [jArray. length ()];
FileUrl = new String [jArray. length ()];
For (int I = 0; I <jArray. length (); I ++) {// Add the data read to the database table to the array through the for Loop
Json_data = jArray. getJSONObject (I );
Ct_id = json_data.getInt ("categoryid ");
Ct_name = json_data.getString ("androidfilename ");
ImageUrl = "http: // 192.168.18.29/Test/MyWebsiteImages/2013_07_to7szt75poNC/760x760/" + ct_name; // only the image path on the server is written to death
FileUrl [count] = imageUrl;
Ct_detail_name = json_data.getString ("filename ");
ImageDetailUrl = "http: // 192.168.18.29/Test/MyWebsiteImages/2013_07_to7szt75poNC/760x760 /"
+ Ct_detail_name;
DetailUrl [count] = imageDetailUrl;
Count ++;
}
} Catch (JSONException e1 ){
E1.printStackTrace ();
} Catch (ParseException e1 ){
E1.printStackTrace ();
}
SetupViews ();
}
Private void setupViews (){
MListview = (ListView) findViewById (R. id. main_lv_list );
Adapter = new MyAdapter (fileUrl, count, this); // send the image URL read from the database to the Adapter.
MListview. setAdapter (adapter );
MListview. setOnScrollListener (mScrollListener );
// Add the Click Event of the Item in the ListView. For the entire Item, if the Item layout is different and different events are added to different components, you just need to handle it separately, I have implemented this function, so I will not talk about it here. I can find another source for research.
MListview. setOnItemClickListener (new OnItemClickListener (){
@ Override
Public void onItemClick (AdapterView <?> Arg0, View arg1, int arg2, long arg3 ){
SetTitle ("Click column" + arg2 + ");
// Bitmap = getBitmap (detailUrl [arg2]);
//
// Buff = Bitmap2Bytes (bitmap );
// Intent mIntent = new Intent ();
// MIntent. putExtra ("image", buff );
// MIntent. setClass (ZhiXunActivity. this,
// ZhiXunDetailActivity. class );
// StartActivity (mIntent );
}
});
}
OnScrollListener mScrollListener = new OnScrollListener () {// load image cache Processing
@ Override
Public void onScrollStateChanged (AbsListView view, int scrollState ){
Switch (scrollState ){
Case OnScrollListener. SCROLL_STATE_FLING:
Adapter. setFlagBusy (true );
Break;
Case OnScrollListener. SCROLL_STATE_IDLE:
Adapter. setFlagBusy (false );
Break;
Case OnScrollListener. SCROLL_STATE_TOUCH_SCROLL:
Adapter. setFlagBusy (false );
Break;
Default:
Break;
}
Adapter. notifyDataSetChanged ();
}
@ Override
Public void onScroll (AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount ){
}
};
}
ImageLoader. java:
Public class ImageLoader {
Private static final String TAG = "ImageLoader ";
Private static final int MAX_CAPACITY = 10; // maximum size of the first-level cache
Private static final long DELAY_BEFORE_PURGE = 10*1000; // regularly clears the cache.
// 0.75 indicates that the loading factor is an empirical value. true indicates that the values are sorted by the recent traffic volume. false indicates that the values are sorted by the insertion order.
Private HashMap <String, Bitmap> mFirstLevelCache = new LinkedHashMap <String, Bitmap> (MAX_CAPACITY/2, 0.75f, true ){
Private static final long serialVersionUID = 1L;
Protected boolean removeEldestEntry (Entry <String, Bitmap> eldest ){
If (size ()> MAX_CAPACITY) {// when the first-level cache threshold is exceeded, the old value is moved from the first-level cache to the second-level cache.
MSecondLevelCache. put (eldest. getKey (), new SoftReference <Bitmap> (eldest. getValue ()));
Return true;
}
Return false;
};
};
// The secondary cache uses soft applications. Soft applications are recycled only when the memory is tight, effectively avoiding oom
Private ConcurrentHashMap <String, SoftReference <Bitmap> mSecondLevelCache = new ConcurrentHashMap <String, SoftReference <Bitmap> (
MAX_CAPACITY/2 );
// Clear cache regularly
Private Runnable mClearCache = new Runnable (){
@ Override
Public void run (){
Clear ();
}
};
Private Handler mPurgeHandler = new Handler ();
// Reset the cache cleanup timer
Private void resetPurgeTimer (){
MPurgeHandler. removeCallbacks (mClearCache );
MPurgeHandler. postDelayed (mClearCache, DELAY_BEFORE_PURGE );
}
/**
* Clear Cache
*/
Private void clear (){
MFirstLevelCache. clear ();
MSecondLevelCache. clear ();
}
/**
* Return the cache. If not, return null.
*
* @ Param url
* @ Return
*/
Public Bitmap getBitmapFromCache (String url ){
Bitmap bitmap = null;
Bitmap = getFromFirstLevelCache (url); // obtain
If (bitmap! = Null ){
Return bitmap;
}
Bitmap = getFromSecondLevelCache (url); // obtain
Return bitmap;
}
/**
* Obtain from the second-level cache
*
* @ Param url
* @ Return
*/
Private Bitmap getFromSecondLevelCache (String url ){
Bitmap bitmap = null;
SoftReference <Bitmap> softReference = mSecondLevelCache. get (url );
If (softReference! = Null ){
Bitmap = softReference. get ();
If (bitmap = null) {// soft reference has been recycled by gc due to memory shortage
MSecondLevelCache. remove (url );
}
}
Return bitmap;
}
/**
* Obtain from the first-level cache
*
* @ Param url
* @ Return
*/
Private Bitmap getFromFirstLevelCache (String url ){
Bitmap bitmap = null;
Synchronized (mFirstLevelCache ){
Bitmap = mFirstLevelCache. get (url );
If (bitmap! = Null) {// place the recently accessed element in the chain header to improve the retrieval speed of the next access to the element (LRU algorithm)
MFirstLevelCache. remove (url );
MFirstLevelCache. put (url, bitmap );
}
}
Return bitmap;
}
/**
* Load the image. If there is any image in the cache, the image will be taken directly from the cache. If there is no image in the cache, the image will be downloaded.
*
* @ Param url
* @ Param adapter
* @ Param holder
*/
Public void loadImage (String url, BaseAdapter adapter, ViewHolder holder ){
ResetPurgeTimer ();
Bitmap bitmap = getBitmapFromCache (url); // read from the cache
If (bitmap = null ){
Holder. mImageView. setImageResource (R. drawable. ic_launcher); // The cache is not set as the default image
ImageLoadTask imageLoadTask = new ImageLoadTask ();
ImageLoadTask.exe cute (url, adapter, holder );
} Else {
Holder. mImageView. setImageBitmap (bitmap); // set it as a cached Image
}
}
/**
* Put into Cache
*
* @ Param url
* @ Param value
*/
Public void addImage2Cache (String url, Bitmap value ){
If (value = null | url = null ){
Return;
}
Synchronized (mFirstLevelCache ){
MFirstLevelCache. put (url, value );
}
}
Class ImageLoadTask extends AsyncTask <Object, Void, Bitmap> {
String url;
BaseAdapter adapter;
@ Override
Protected Bitmap doInBackground (Object... params ){
Url = (String) params [0];
Adapter = (BaseAdapter) params [1];
Bitmap drawable = loadImageFromInternet (url); // obtain the network image
Return drawable;
}
@ Override
Protected void onPostExecute (Bitmap result ){
If (result = null ){
Return;
}
AddImage2Cache (url, result); // put it into the cache
Adapter. notifyDataSetChanged (); // trigger the getView method execution. In this case, getView actually obtains the cached image.
}
}
Public Bitmap loadImageFromInternet (String url ){
Bitmap bitmap = null;
HttpClient client = AndroidHttpClient. newInstance ("Android ");
HttpParams params = client. getParams ();
HttpConnectionParams. setConnectionTimeout (params, 3000 );
HttpConnectionParams. setSocketBufferSize (params, 3000 );
HttpResponse response = null;
InputStream inputStream = null;
HttpGet httpGet = null;
Try {
HttpGet = new HttpGet (url );
Response = client.exe cute (httpGet );
Int stateCode = response. getStatusLine (). getStatusCode ();
If (stateCode! = HttpStatus. SC _ OK ){
Log. d (TAG, "func [loadImage] stateCode =" + stateCode );
Return bitmap;
}
HttpEntity entity = response. getEntity ();
If (entity! = Null ){
Try {
InputStream = entity. getContent ();
Return bitmap = BitmapFactory. decodeStream (inputStream );
} Finally {
If (inputStream! = Null ){
InputStream. close ();
}
Entity. consumeContent ();
}
}
} Catch (ClientProtocolException e ){
HttpGet. abort ();
E. printStackTrace ();
} Catch (IOException e ){
HttpGet. abort ();
E. printStackTrace ();
} Finally {
(AndroidHttpClient) client). close ();
}
Return bitmap;
}
}
MyAdapter. java:
Public class MyAdapter extends BaseAdapter {
Private static final String TAG = "MyAdapter ";
Private boolean mBusy = false;
Public void setFlagBusy (boolean busy ){
This. mBusy = busy;
}
Private ImageLoader mImageLoader;
Private int mCount;
Private Context mContext;
String [] URLS;
Public MyAdapter (String [] URLS, int count, Context context ){
This. URLS = URLS;
This. mCount = count;
This. mContext = context;
MImageLoader = new ImageLoader ();
}
@ Override
Public int getCount (){
Return mCount;
}
@ Override
Public Object getItem (int position ){
Return position;
}
@ Override
Public long getItemId (int position ){
Return position;
}
@ Override
Public View getView (int position, View convertView, ViewGroup parent ){
Log. d (TAG, "position =" + position + ", convertView =" + convertView );
ViewHolder viewHolder = null;
If (convertView = null ){
ConvertView = LayoutInflater. from (mContext). inflate (R. layout. list_item, null); // This process is quite time-consuming.
ViewHolder = new ViewHolder ();
ViewHolder. mTextView = (TextView) convertView. findViewById (R. id. TV _tips );
ViewHolder. mImageView = (ImageView) convertView. findViewById (R. id. iv_image );
ConvertView. setTag (viewHolder );
} Else {
ViewHolder = (ViewHolder) convertView. getTag ();
}
String url = "";
Url = URLS [position % URLS. length];
If (! MBusy ){
MImageLoader. loadImage (url, this, viewHolder );
ViewHolder. mTextView. setText ("--" + position + "-- IDLE | TOUCH_SCROLL ");
} Else {
Bitmap bitmap = mImageLoader. getBitmapFromCache (url );
If (bitmap! = Null ){
ViewHolder. mImageView. setImageBitmap (bitmap );
} Else {
ViewHolder. mImageView. setImageResource (R. drawable. ic_launcher );
}
ViewHolder. mTextView. setText ("--" + position + "-- FLING ");
}
Return convertView;
}
Static class ViewHolder {
TextView mTextView;
ImageView mImageView;
}
}