首页 > 编程技术 > android

android开发之ListView异步加载图片

发布时间:2016-9-20 20:00

本文章分享和下关于android开发之ListView异步加载图片 ,有需了解的朋友可以参考一下。

ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,不用让用户等待下去,下面就说实现方法,先贴上主方法的代码:

 代码如下 复制代码
package cn.wangmeng.test;
 
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
 
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
 
public class AsyncImageLoader {
 
private HashMap<String, SoftReference<Drawable>> imageCache;
 
public AsyncImageLoader() {
imageCache = new HashMap<String, SoftReference<Drawable>>();
}
 
public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
if (imageCache.containsKey(imageUrl)) {
SoftReference<Drawable> softReference = imageCache.get(imageUrl);
Drawable drawable = softReference.get();
if (drawable != null) {
return drawable;
}
}
final Handler handler = new Handler() {
public void handleMessage(Message message) {
imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
}
};
new Thread() {
@Override
public void run() {
Drawable drawable = loadImageFromUrl(imageUrl);
imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
Message message = handler.obtainMessage(0, drawable);
handler.sendMessage(message);
}
}.start();
return null;
}
 
public static Drawable loadImageFromUrl(String url) {
URL m;
InputStream i = null;
try {
m = new URL(url);
i = (InputStream) m.getContent();
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Drawable d = Drawable.createFromStream(i, "src");
return d;
}
 
public interface ImageCallback {
public void imageLoaded(Drawable imageDrawable, String imageUrl);
}
 
}

以上代码是实现异步获取图片的主方法,SoftReference是软引用,是为了更好的为了系统回收变量,重复的URL直接返回已有的资源,实现回调函数,让数据成功后,更新到UI线程。
几个辅助类文件:

 代码如下 复制代码
package cn.wangmeng.test;
 
public class ImageAndText {
private String imageUrl;
private String text;
 
public ImageAndText(String imageUrl, String text) {
this.imageUrl = imageUrl;
this.text = text;
}
public String getImageUrl() {
return imageUrl;
}
public String getText() {
return text;
}
}
package cn.wangmeng.test;
 
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
 
public class ViewCache {
 
private View baseView;
private TextView textView;
private ImageView imageView;
 
public ViewCache(View baseView) {
this.baseView = baseView;
}
 
public TextView getTextView() {
if (textView == null) {
textView = (TextView) baseView.findViewById(R.id.text);
}
return textView;
}
 
public ImageView getImageView() {
if (imageView == null) {
imageView = (ImageView) baseView.findViewById(R.id.image);
}
return imageView;
}
 
}

ViewCache是辅助获取adapter的子元素布局

 代码如下 复制代码
package cn.wangmeng.test;
 
import java.util.List;
 
import cn.wangmeng.test.AsyncImageLoader.ImageCallback;
 
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
 
public class ImageAndTextListAdapter extends ArrayAdapter<ImageAndText> {
 
private ListView listView;
private AsyncImageLoader asyncImageLoader;
 
public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
super(activity, 0, imageAndTexts);
this.listView = listView;
asyncImageLoader = new AsyncImageLoader();
}
 
public View getView(int position, View convertView, ViewGroup parent) {
Activity activity = (Activity) getContext();
 
// Inflate the views from XML
View rowView = convertView;
ViewCache viewCache;
if (rowView == null) {
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(R.layout.image_and_text_row, null);
viewCache = new ViewCache(rowView);
rowView.setTag(viewCache);
} else {
viewCache = (ViewCache) rowView.getTag();
}
ImageAndText imageAndText = getItem(position);
 
// Load the image and set it on the ImageView
String imageUrl = imageAndText.getImageUrl();
ImageView imageView = viewCache.getImageView();
imageView.setTag(imageUrl);
Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, new ImageCallback() {
public void imageLoaded(Drawable imageDrawable, String imageUrl) {
ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
if (imageViewByTag != null) {
imageViewByTag.setImageDrawable(imageDrawable);
}
}
});
if (cachedImage == null) {
imageView.setImageResource(R.drawable.default_image);
}else{
imageView.setImageDrawable(cachedImage);
}
// Set the text on the TextView
TextView textView = viewCache.getTextView();
textView.setText(imageAndText.getText());
 
return rowView;
}
 
}


ImageAndTextListAdapter是实现ListView的Adapter,里面有个技巧就是imageView.setTag(imageUrl),setTag是存储数据的,这样是为了保证在回调函数时,listview去更新自己对应item,大家仔细阅读就知道了。
最后贴出布局文件:

 代码如下 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
 
<ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
 
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
 
</LinearLayout>
本文章分享一些Android平台中一些免费的UI库及组件资源,有需要的朋友可以下载。

短短数年时间 Android 平台就已经形成了一个庞大而活跃的开发者社区。许多社区开发的项目业已进入成熟阶段,甚至可以用于商业的软件生产中,且不用担心质量问题。
本文编译自 androiduipatterns,意在分享一些免费、开源的 Android UI 库及组件资源。 

 

1. GreenDroid  

 

 

 

该项目可以实现下列的 UI 设计:

  • 动作栏(Action Bar)
  • 快捷动作(Quick Action)
  • 工作区(Workspace)
  • 动态列表(Dynamic List)

以及许多更有用的组件。

项目网站 / ps://market.android.com/details?id=com.cyrilmottier.android.gdcatalog" target="_blank">示例 

 

 

应用程序屏幕截图:

   

 

2. ActionBarSherlock  

 

 

在Google针对手机的动作条API推出前,该项目一直与ICS一起使用。Jake最近将项目拓展到了动作条之外。这里也有针对工作区等的组件。 

 

          项目网站 / 示例  

 

  3. Android Compatibility Package 

 

 

 

  这是一个来自Google Android库的官方扩展。Compatibility Package顾名思义就是Android官方针对旧平台版本所不支持的API或是Android Framework没有提供的函数库,将其打包发布。它包含了许多非常有用的API。该包同样包含工作区UI设计的实现。 

 

 4. iosched  

 

 

 

   这是一个官方的Google I/O的应用(同样可用在GDD,Google Developer Day)(注:Google I/O是Google每年都会举办的历时两天的开发者大会,该大会谈及各种技术问题。开发人员会提供非常多的示例来展示他们的技术。这个项目专门为了这个会议提供了一个Android应用程序。)。该应用程序实现了大量的UI设计,成为Google Android设备拥护者的参考标准。强烈推荐使用该应用程序的仪表盘UI设计模式。(Google代码链接:Dashboard.java) 


  项目网站:http://code.google.com/p/iosched/ 

 

 5. Android-Viewflow 

 

该项目的工作区UI设计模式与Google Docs所使用非常相似。 

项目网站:https://github.com/pakerfeldt/android-viewflow 

6. android-coverflow 

该项目可以用于完成一个cover flow。在这个项目网站的视频中可以得到更多的信息。 

项目网站:http://code.google.com/p/android-coverflow/ 

7. android-viewbadger 

该项目让devs无需修改布局文件(layout file)即可显示badges。 

项目网站:https://github.com/jgilfelt/android-viewbadger  

 

8. android-pulltorefresh 

 

该项目实现动态列表/下拉刷新(pull to refresh)的UI设计。 

项目网站:https://github.com/johannilsson/android-pulltorefresh 

9. Android-ViewPagerIndicator 

该项目可以用于实现工作区的UI设计。 

        项目网站/示例  

分享一篇关于android调用系统短信Intent时将预填接收号码和内容 ,有需要的朋友可以参考一下下。

前段世界在一个应用中调用系统自带的发送短信的Intent,但是接收者的号码一直穿不过去,代码如下:

 代码如下 复制代码
Uri smsToUri = Uri.parse("smsto:123456");
Intent sendIntent = new Intent(Intent.ACTION_VIEW, smsToUri);
sendIntent.putExtra("sms_body", "Hello dear world");
sendIntent.setType("vnd.android-dir/mms-sms");
startActivity(sendIntent);

然后查到原因是这个Uri格式的无法自动解析出来,需要另外设置下接收者地址,代码如下:

 代码如下 复制代码
sendIntent.putExtra("address", "123456");
文章介绍了一篇关于android手机开发自定义标题栏,有需要的朋友可以参考一下下。

一、概述

      每一个应用程序默认的标题栏(注意与状态栏的区别)只有一行文字(新建工程时的名字),而且颜色、大小等都是固定的,给人的感觉比较单调。但当程序需要美化的时候,那么修改标题栏是就是其中一项内容,虽然Android已经定义了很多样式资源,但更多时候我们需要使用的是自己定义的样式。


二、要求

     使用自己定义的样式来修改程序的标题栏。


三、实现

     新建工程MyTitle,不用修改main.xml文件,在/res/layout目录下新建布局文件title.xml,在里面添加一个TextView和一个Button,完整的title.xml文件如下:

 代码如下 复制代码

<?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal"
     >
    
     <TextView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="这是定制的标题栏"
         android:textStyle="bold"
         android:textColor="#FFFF0000"     
         />
    
     <Button
         android:id="@+id/button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="点我"
         />
 
 </LinearLayout>

在/res/values目录下新建titlestyle.xml文件,在里面定义两个style,一个用来修改标题栏的大小,一个用来修改标题栏的背景颜色,如下:

 代码如下 复制代码

<?xml version="1.0" encoding="utf-8"?>
 
 <resources>
    
     <style name="TitleBackgroundColor">
         <item name="android:background">#FF0000FF</item>
     </style>
    
     <style name="titlestyle" parent="android:Theme" >
         <item name="android:windowTitleSize">40dip</item>   
         <item name="android:windowTitleBackgroundStyle">@style/TitleBackgroundColor</item>
     </style>
    
 </resources>

修改AndroidManifest.xml文件,在application标签下添加一行:

 代码如下 复制代码
 android:theme="@style/titlestyle"

最后,修改MyTitleActivity.java文件,设置使用自定义的标题栏,实现Button按钮的监听,如下:

 代码如下 复制代码

package com.nan.title;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.View;
 import android.view.Window;
 import android.widget.Button;
 import android.widget.Toast;
 
 public class MyTitleActivity extends Activity
 {
     private Button mButton = null;
    
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState)
     {
         super.onCreate(savedInstanceState);
         //使用自定义标题栏
         requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
         setContentView(R.layout.main);
         //使用布局文件来定义标题栏
         getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title);
        
         mButton = (Button)this.findViewById(R.id.button);
         //按钮监听
         mButton.setOnClickListener(new View.OnClickListener()
         {
            
             @Override
             public void onClick(View v)
             {
                 // TODO Auto-generated method stub
                 displayToast("Clicked!");
             }
         });
             
     }
    
     //显示Toast函数
     private void displayToast(String s)
     {
         Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
     }
    
 }

注意上面程序的第20~23行的顺序不能调乱。

运行该程序:

 

点击一下“点我”按钮:

 

在编写云笔记时需要调用auth2.0协议,在调用是老出现javax.net.ssl.SSLPeerUnverifiedException: No peer certificate的错误,

根据有关资料解决如下:
1、编写SSLSocketFactoryEx,以代替原有的SSLSocketFactory,

代码如下:

 代码如下 复制代码

package com.nbcio.baishicha.yunbiji;

import java.io.IOException;

import java.net.Socket;

import java.net.UnknownHostException;

import java.security.KeyManagementException;

import java.security.KeyStore;

import java.security.KeyStoreException;

import java.security.NoSuchAlgorithmException;

import java.security.UnrecoverableKeyException;

 

import javax.net.ssl.SSLContext;

import javax.net.ssl.TrustManager;

import javax.net.ssl.X509TrustManager;

 

import org.apache.http.conn.ssl.SSLSocketFactory;

 

public class SSLSocketFactoryEx extends SSLSocketFactory {

 

SSLContext sslContext = SSLContext.getInstance("TLS");

 

public SSLSocketFactoryEx(KeyStore truststore)

throws NoSuchAlgorithmException, KeyManagementException,

KeyStoreException, UnrecoverableKeyException {

super(truststore);

 

TrustManager tm = new X509TrustManager() {

 

public java.security.cert.X509Certificate[] getAcceptedIssuers() {

return null;

}

 

@Override

public void checkClientTrusted(

java.security.cert.X509Certificate[] chain, String authType)

throws java.security.cert.CertificateException {

 
}
 

@Override

public void checkServerTrusted(

java.security.cert.X509Certificate[] chain, String authType)

throws java.security.cert.CertificateException {

 

}

};

sslContext.init(null, new TrustManager[] { tm }, null);

}


@Override

public Socket createSocket(Socket socket, String host, int port,

boolean autoClose) throws IOException, UnknownHostException {

return sslContext.getSocketFactory().createSocket(socket, host, port,

autoClose);

}

 

@Override

public Socket createSocket() throws IOException {

return sslContext.getSocketFactory().createSocket();

}

}

2、编写新的HttpClient  getNewHttpClient来代替原有的DefaultHttpClient,代码如下:
public static HttpClient getNewHttpClient() {
   try {
       KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
       trustStore.load(null, null);
 
       SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
       sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
 
       HttpParams params = new BasicHttpParams();
       HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
       HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
 
       SchemeRegistry registry = new SchemeRegistry();
       registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
       registry.register(new Scheme("https", sf, 443));
 
       ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
 
       return new DefaultHttpClient(ccm, params);
   } catch (Exception e) {
       return new DefaultHttpClient();
   }
}

3、在postRequest调用的时候如下方式就可以:

 代码如下 复制代码

HttpResponse httpResponse =  (HttpResponse) getNewHttpClient().execute(postMethod);
Related posts:

标签:[!--infotagslink--]

您可能感兴趣的文章: