Android异步加载图片与文字(一)

最近一直在忙期末考试的事,因为是大学最后的几场考试,所以不能挂,就一直在努力复习,也很久没碰android了T_T(手真的很痒!!!)今天我学着做了Android的异步加载,将图片和文字信息显示在ListView里。

先来张效果图:


估计有些人应该会熟悉这些吧,因为这些数据是从慕课网的接口里拿到的返回的是json的数据,所以我们要解析json数据

首先是布局文件,主界面就是一个listView没啥,然后是item的布局,一张图片加上标题和内容 item_layout.xml:

<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="wrap_content"
    android:padding="4dp" >

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:src="@drawable/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:paddingLeft="4dp" >

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:maxLines="1"
            android:text="title"
            android:textSize="15sp" />

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:maxLines="3"
            android:text="content"
            android:textSize="10sp" />
    </LinearLayout>

</LinearLayout>

然后就是MainActivity的代码了,这里我使用了AsyncTask类来进行通信,来异步加载网上的数据。Android中实现异步操作的有handler和asynctask。handler是为每个任务开启线程,然后发送信息到主线程,完成主界面的更新。优点是结构清晰,对于多个任务时,也是效果明显。缺点是代码容易臃肿。asynctask是android是提供的轻量级的异步类,可直接继承asynctask,实现异步操作,并提供接口表示当前异步操作的进度(通过接口实现UI的更新),最后返回结果到UI主线程。优点是简单便捷,过程可控。

AsyncTask的定义:public abstract class AsyncTask<params,progress,result>{}

三种泛型分别表示“启动任务执行的输入参数”、“后台任务的进度”、“后台计算结果的类型”。如果不需要获取进度,可以用Java.lang.Void代替progress。

继承AsyncTask,一般会覆写这几个方法:

1.execute(Params...params)执行一个异步任务,需要我们在代码中调用这个方法,触发异步任务的执行

2.onPreExecute(),在execute(Params...params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记

3.doInBackground(Params...params),在onPreExecute()完成后立即执行,用于执行费时的操作,此方法将接受输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress...values)来更新进度信息。

4.onPregressUpdate(Progress...values),在调用publishProgress(Progress...values)时,此方法被执行,直接将进度信息更新到UI组件上。

5.onPostExecute(Result result),当后台操作时,此方法将会被调用,计算结果作为参数传递到此方法中,直接将结果显示到UI组件上。

(复制别人的!)在使用的时候,有几点需要格外注意:

1.异步任务的实例必须在UI线程中创建。

2.execute(Params... params)方法必须在UI线程中调用。

3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。

4.不能在doInBackground(Params... params)中更改UI组件的信息。

5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。

上代码:

public class MainActivity extends Activity {
      private ListView listView;
      private static String URL = "http://www.imooc.com/api/teacher?type=4&num=30";

      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.listview);
        new newsAsyncTask().execute(URL);
}
      /**
      * 实现网络的异步访问
      *
      */
      class newsAsyncTask extends AsyncTask<String, Void, List<NewsBean>> {

        @Override
       protected List<NewsBean> doInBackground(String... params) {
       // TODO Auto-generated method stub
       // params传递的网址
       return getJsonData(params[0]);
       }
        @Override
      protected void onPostExecute(List<NewsBean> result) {
       // TODO Auto-generated method stub
        super.onPostExecute(result);
        NewsAdapter adapter = new NewsAdapter(MainActivity.this, result);
        listView.setAdapter(adapter);
       }
       }
         /**
         * 将URL对应的json数据转化为所封装的newsBean对象
         * 
         * @param url
         * @return
         */
       public List<NewsBean> getJsonData(String url) {
       List<NewsBean> newsBeanList = new ArrayList<NewsBean>();
       String jsonString;
       NewsBean newsBean;
      try {
         jsonString = readStream(new URL(url).openStream());
         JSONObject jsonObject;
      try {
         jsonObject = new JSONObject(jsonString);
         JSONArray array = jsonObject.getJSONArray("data");
         for (int i = 0; i < array.length(); i++) {
         jsonObject = array.getJSONObject(i);
         newsBean = new NewsBean();
         newsBean.newsIconUrl = jsonObject.getString("picSmall");
         newsBean.newsTitle = jsonObject.getString("name");
         newsBean.newsContent = jsonObject.getString("description");
         newsBeanList.add(newsBean);
         }
         } catch (JSONException e) {
        // TODO Auto-generated catch block
          e.printStackTrace();
       }
       } catch (MalformedURLException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
       } catch (IOException e) {
       // TODO Auto-generated catch block
        e.printStackTrace();
      }
        return newsBeanList;
    }
      /**
      * 解析网页返回的数据
      */
      private String readStream(InputStream is) {
      InputStreamReader isr;
      String result = "";
      String line = "";
      try {
       isr = new InputStreamReader(is, "utf-8");
       BufferedReader br = new BufferedReader(isr);
       while ((line = br.readLine()) != null) {
       result += line;
      }
      } catch (UnsupportedEncodingException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
     return result;
     }


在异步操作的费时操作中进行json数据的获得,json数据的解析不算难,能看懂

public class NewsBean {
String newsIconUrl;
String newsTitle;
String newsContent;
}

然后是适配器的代码:

  public class NewsAdapter extends BaseAdapter implements OnScrollListener {
      private List<NewsBean> mList;
      private LayoutInflater mInflater;
      private ImageLoader imageLoader;
   public NewsAdapter(Context contxet, List<NewsBean> data) {
          mList = data;
          mInflater = LayoutInflater.from(contxet);
           imageLoader = new ImageLoader();
      }
         @Override
     public int getCount() {
        // TODO Auto-generated method stub
         return mList.size();
     }
       @Override
     public Object getItem(int position) {
      // TODO Auto-generated method stub
      return mList.get(position);
     }
      @Override
     public long getItemId(int position) {
      // TODO Auto-generated method stub
       return position;
      }
       @Override
      public View getView(int position, View convertView, ViewGroup parent) {
      // TODO Auto-generated method stub
     NewsBean newsBean = new NewsBean();
     ViewHolder viewHolder;
     if (convertView == null) {
      convertView = mInflater.inflate(R.layout.item_layout, null);
      viewHolder = new ViewHolder();
      viewHolder.newsIcon = (ImageView) convertView
     .findViewById(R.id.iv_icon);
      viewHolder.newsTitle = (TextView) convertView
     .findViewById(R.id.tv_title);
      viewHolder.newsContent = (TextView) convertView
     .findViewById(R.id.tv_content);
     convertView.setTag(viewHolder);
     } else {
     viewHolder = (ViewHolder) convertView.getTag();
    }
     viewHolder.newsIcon.setImageResource(R.drawable.ic_launcher);
     String url = mList.get(position).newsIconUrl;
     viewHolder.newsIcon.setTag(url);
    // new ImageLoader().showImageByThread(viewHolder.newsIcon, url);
     imageLoader.showImageByAsyncTask(viewHolder.newsIcon, url);
     viewHolder.newsTitle.setText(mList.get(position).newsTitle);
     viewHolder.newsContent.setText(mList.get(position).newsContent);
    return convertView;
    }
   class ViewHolder {
    private ImageView newsIcon;
    private TextView newsTitle;
    private TextView newsContent;
   }

还有这里用到了ImageLoader这个类,下期再说。适配器里面使用了settag是为了使每个Url对应各自的item的图片,防止ListView在滑动过程,出现图片错位的情况。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值