zoukankan      html  css  js  c++  java
  • 初识安卓之仿微博界面的实现

    以下为主界面上负责显示的代码:
    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:  }
  • 相关阅读:
    tcp粘包解决
    socket网络编程
    logging模块
    异常处理
    hashlib configparser模块
    列表推导式和生成器表达式和内置函数
    迭代器与生成器
    装饰器
    函数
    文件操作
  • 原文地址:https://www.cnblogs.com/94007boy/p/2790990.html
Copyright © 2011-2022 走看看