初识安卓之仿微博界面的实现

以下为主界面上负责显示的代码:
1:
public class MainActivity extends Activity {
   2:      private ImageService imageService;
   3:      private List<Blog> blogs;
   4:      //activity一创建执行的代码
   5:      public void onCreate(Bundle savedInstanceState) {
   6:          super.onCreate(savedInstanceState);
   7:          setContentView(R.layout.main);
   8:          try {
   9:              //先拿到负责处理图像和封装微博对象的两个服务类对象
  10:              imageService = new ImageService(this);
  11:              BlogService blogService = new BlogService();                
 //通过blogService的get方法,从服务器中请求xml资源,并对xml进行解析,封装对象,得到一个微博对象集合
  13:              blogs = blogService.getBlogs();
  14:              //获取ListView控件对象
  15:              ListView blogLV = (ListView) findViewById(R.id.blogLV);
  16:              //设置ListView控件对象的适配器,用来向列表中添加包含了微博对象的各个item元素
  17:              blogLV.setAdapter(adapter);
  18:          } catch (Exception e) {
  19:              e.printStackTrace();
  20:              Toast.makeText(this, "服务器忙!", 0).show();
  21:          }
  22:      }
  23:      private BaseAdapter adapter = new BaseAdapter() {
  24:          //listview中用来获取一个行信息的函数:        
  25:              //getview方法作用,listview中显示一条item就调用一次该方法,创建一个条目视图        
  26:              //需要传三个参数:当前条目位置,当前条目载体(是否重用),当前条目父级
  27:          public View getView(int position, View convertView, ViewGroup parent) {
  28:              //把每个item填充到listview中的行里,销毁的拿来重新利用,提高浏览的速度
  29:              View view = convertView == null ?                     
  30:                      View.inflate(getApplicationContext(), R.layout.item, null) : convertView;            
  31:              //生成一个完整的item,设置它里面的所有内容:                    
  32:              //获取头像控件对象
  33:              final ImageView portraitIV =(ImageView) view.findViewById(R.id.portraitIV);        
  34:              //获取微博里的图片控件对象
  35:              final ImageView picIV =(ImageView) view.findViewById(R.id.picIV);    
  36:              //获取名字文本控件对象
  37:              TextView nameTV = (TextView) view.findViewById(R.id.nameTV);
  38:              //获取微博内容文本控件对象
  39:              TextView contentTV = (TextView) view.findViewById(R.id.contentTV);
  40:              //获取微博来源内容文本控件对象
  41:              TextView fromTV = (TextView) view.findViewById(R.id.fromTV);
  42:              //得到当前位置处的那个微博对象,position代表第几个条目,从0开始,正好和集合的下标一致
  43:              final Blog blog = blogs.get(position);
  44:              // 把blog中的数据添加到TextView, ImageView中
  45:              nameTV.setText(blog.getName());                
  46:              contentTV.setText(blog.getContent());            
  47:              fromTV.setText(blog.getFrom());            
  48:              //获取解析到的图片的方法:            
  49:              //原理:解析到的只是图片的地址,所以要得到图片,最好重新开一个线程,去访问服务器上的图片
  50:              try {
  51:                  //把微博对象中的图片属性值(就是图片的地址),传给imageService的get方法,让它去访问,就可以得到一个图片
  52:                  portraitIV.setImageBitmap(imageService.getImage(blog.getPortrait()));                
  53:              } catch (Exception e) {                
  54:                  e.printStackTrace();
  55:              }
  56:              //设置微博对象中的微博图片同上
  57:              try {                
  58:                  picIV.setImageBitmap(imageService.getImage(blog.getPic()));                
  59:              } catch (Exception e) {                
  60:                  e.printStackTrace();
  61:              }
  62:              return view;
  63:          }
  64:          public long getItemId(int position) {            
  65:              return position;
  66:          }        
  67:          //从微博对象集合blogs中,找到当前位置处的那个微博对象,并返回,position代表第几个条目,从0开始,正好和集合的下标一致
  68:          public Object getItem(int position) {            
  69:              return blogs.get(position);
  70:          }        
  71:          public int getCount() {
  72:              return blogs.size();
  73:          }
  74:      };
  75:  }

以下为负责处理请求图片逻辑的服务层代码

   1:  public class ImageService {
   2:      private Context context;
   3:   
   4:      public ImageService(Context context) {
   5:          this.context = context;
   6:      }
   7:      //bitmap位图类,安卓中用来表示图片的类,自定义一个从服务器获得图片的方法,接受一个图片地址
   8:      public Bitmap getImage(String address) throws Exception {
   9:          if (address == null)
  10:              return null;        
  11:          //创建连接对象
  12:          URL url = new URL(address);        
  13:          //打开连接
  14:          HttpURLConnection conn = (HttpURLConnection) url.openConnection();    
  15:          //设置连接超时
  16:          conn.setConnectTimeout(3000);
  17:          //创建一个文件路径对象,目录是文件缓存地址,文件名是图片的网络地址
  18:          File cacheFile = new File(context.getCacheDir(), URLEncoder.encode(address));        
  19:          if (cacheFile.exists()) {
//路径对象下的文件对象存在,说明之前访问过了,获取其最后修改时间, 设置请求头,再向服务器去请求这个图片
  21:              //以便能让服务器判断这个图片最近有没有修改过            
  22:              conn.setIfModifiedSince(cacheFile.lastModified());    
  23:          }
  24:          //获取服务器响应
  25:          int code = conn.getResponseCode();
  26:          
  27:          //资源被修改了或者第一次访问该资源都是200
  28:          if (code == 200) {
  29:              //利用自定义的工具类,读取服务器响应回的输入流并转为字节数组型数据
  30:              byte[] data = Util.read(conn.getInputStream());    
  31:              //创建一个位图对象的方法:利用工厂类把字节数据解码为图片
  32:              Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);    
  33:              // 存储图片到本地, 用作缓存. 建议新线程中处理
  34:              bm.compress(CompressFormat.JPEG, 100, new FileOutputStream(cacheFile));    
  35:              return bm;    
  36:              //304表示资源没有被修改过,只要不是304,资源要么被修改了,要么是第一次访问
  37:          } else if (code == 304) {
  38:              Bitmap bm = BitmapFactory.decodeFile(cacheFile.getAbsolutePath());        // 读取cacheFile, 生成Bitmap
  39:              return bm;
  40:          }        
  41:          throw new NetworkErrorException("连接出错: " + code);
  42:      }
  43:   
  44:  }
 
以下代码为负责从服务器请求微博数据的服务层代码:
 
   1:  public class BlogService {
   2:   
   3:      /**
   4:       * 请求服务端, 得到包含数据的XML, 解析XML, 得到List<Blog>
   5:       * @return    包含Blog对象的List集合
   6:       */
   7:      public List<Blog> getBlogs() throws Exception {        
   8:          //如果服务器发过来的是blogs.js类型的数据,而不是blogs.xml,解析方式如下“
   9:          
  10:          //创建连接对象,如果服务器是以js的形式发回微博内容。则调用parseJSON方法
  11:          URL url = new URL("http://192.168.1.253:8080/15.Web/blogs.js"); 
  12:          
  13:          //创建连接对象,如果服务器是以xml的形式发回微博内容。则调用parseXML方法
  14:          //URL url = new URL("http://192.168.1.253:8080/15.Web/blogs.xml"); 
  15:          
  16:          //打开该连接
  17:          HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  18:          conn.setConnectTimeout(3000);
  19:          
  20:          int code = conn.getResponseCode();
  21:          if (code == 200) {
  22:              //访问成功,执行解析方法
  23:              return parseJSON(conn.getInputStream());
  24:          }
  25:          throw new NetworkErrorException("网络异常: " + code);
  26:      }
  27:      
  28:      //服务器以js的形式发回微博内容。调用parseJSON方法
  29:      private List<Blog> parseJSON(InputStream inputStream) throws Exception {
  30:          List<Blog> blogs = new ArrayList<Blog>();
  31:          // 读取服务端写回的js数据,将服务器发来的输入流封装到一个字节数组中
  32:          byte[] data = Util.read(inputStream);    
  33:          //将返回的字节数组转为字符串,该字符串包含了很多表中单元,一个单元代表一个微博信息
  34:          String json = new String(data);                
  35:          //将包含所有微博数据的字符串封装成一个JSON数组对象,数组中每个成员是一条微博信息
  36:          JSONArray arr = new JSONArray(json);    
  37:          //遍历数组,解析每条微博
  38:          for (int i = 0; i < arr.length(); i++) {    // 循环遍历数组
  39:              // 得到每一个JSON对象
  40:              JSONObject obj = arr.getJSONObject(i);    
  41:              //准备封装成对象
  42:              Blog blog = new Blog();
  43:              //封装对象的过程:
  44:              blog.setPortrait(obj.getString("portrait"));    // 获取JSON对象中的属性, 设置给Blog对象
  45:              blog.setName(obj.getString("name"));
  46:              blog.setContent(obj.getString("content"));
  47:              //将图片的路径作为图片属性放到微博对象中
  48:              String pic = obj.getString("pic");
  49:              //如果微博中本来就没有图片,则设置null即可
  50:              blog.setPic(pic.equals("null") ? null : pic);
  51:              blog.setFrom(obj.getString("from"));
  52:              blogs.add(blog);
  53:          }
  54:          
  55:          return blogs;
  56:      }
  57:   
  58:      //服务器以xml的形式发回微博内容。调用parseXML方法
  59:      private List<Blog> parseXML(InputStream inputStream) throws Exception {
  60:          List<Blog> blogs = new ArrayList<Blog>();
  61:          Blog blog = null;
  62:          
  63:          XmlPullParser parser = Xml.newPullParser();
  64:          parser.setInput(inputStream, "UTF-8");
  65:          for (int type = parser.getEventType(); type != XmlPullParser.END_DOCUMENT; type = parser.next()) {
  66:              if (type == XmlPullParser.START_TAG) {
  67:                  if ("blog".equals(parser.getName())) {
  68:                      blog = new Blog();
  69:                      blogs.add(blog);
  70:                  } else if ("portrait".equals(parser.getName())) {
  71:                      blog.setPortrait(parser.nextText());
  72:                  } else if ("name".equals(parser.getName())) {
  73:                      blog.setName(parser.nextText());
  74:                  } else if ("content".equals(parser.getName())) {
  75:                      blog.setContent(parser.nextText());
  76:                  } else if ("pic".equals(parser.getName())) {
  77:                      blog.setPic(parser.nextText());
  78:                  } else if ("from".equals(parser.getName())) {
  79:                      blog.setFrom(parser.nextText());
  80:                  }
  81:              }
  82:          }
  83:          return blogs;
  84:      }
  85:  }

使用到的自定义工具类:读取服务器返回的输入流,转为字节数组

 

   1:  public class Util {
   2:   
   3:      /**
   4:       * 读取输入流中的数据, 返回
   5:       * @param in    要读取数据的输入流
   6:       * @return        输入流中的数据
   7:       */
   8:      public static byte[] read(InputStream in) throws IOException {
   9:          ByteArrayOutputStream baos = new ByteArrayOutputStream();
  10:          byte[] buffer = new byte[1024];
  11:          int len;
  12:          while ((len = in.read(buffer)) != -1)
  13:              //为了提高效率,砍掉数组中空白内容,写入字符数组的某一部分,而不是把字符数组整个写入
  14:              baos.write(buffer, 0, len);
  15:          in.close();
  16:          baos.close();
  17:          return baos.toByteArray();
  18:      }
  19:  }
原文地址:https://www.cnblogs.com/94007boy/p/2790990.html