zoukankan      html  css  js  c++  java
  • Android客户端获取服务器的json数据(二)

     这一周课很多,所以没有及时的接上。

    现在的我不打算再拼命的做码农了,而是尽量的做总结。把以前写过的一些代码回忆一下,把以前有过的思路再重新寻觅一回。似乎,我好多废话。

    在做Android应用程序开发时,有很多应用都会获取由Web Server返回的数据,有的可能是xml数据,有可能是json数据。他们各有应用范围。我继续总结一下获取网络json数据的一些idea。这里先分析一下业务逻辑,UI稍后再唠叨。

    1.分析一下手机购物应用的执行过程。

    首次执行一个MainActivity,此activity的功能是构成main UI(即下方有个Tab 菜单),由于我的没个Activity都是继承了上文中的IMActivity接口,这里实现初始化init()方法。我们都知道Activity的生命周期,所以我在onResume()方法里调用init()方法。并且,初始化方法完成几个任务。

      1.1 检查网络连接

        android系统有提供检测网络的api。我们可以很方便的调用。我们可以把检查网络的方法封装在一个工具类里(可根据自己的programing style)

      

    View Code
    package com.mpros.util;
    
    import android.content.Context;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    
    /***
     * 工具类,检查当前网络状态
     * 
     * @author shuimu
     * 
     */
    public class NetUtil {
    
        public static boolean checkNet(Context context) {
    
            // 获取手机所以连接管理对象(包括wi-fi,net等连接的管理)
    
            ConnectivityManager conn = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            if (conn != null) {
                // 网络管理连接对象
                NetworkInfo info = conn.getActiveNetworkInfo();
                
                if(info != null && info.isConnected()) {
                    // 判断当前网络是否连接
                    if (info.getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
                
            }
    
            return false;
        }
    }

      1.2如果网络连接正常,启动服务Service。否则提醒用户网络连接异常。网络连接异常的方法,我封装在了MainService中,可以直接invoke。

        

    View Code
        @Override
        protected void onResume() {
    
            super.onResume();
            init();
        }
    
        @Override
        public void init() {
            if (NetUtil.checkNet(this)) {
                Intent startService = new Intent("com.mpros.service.MainService");
                this.startService(startService);
            } else {
                MainService.alerNetErr(this);
            }
        }

      

    2.当MainActivity执行到onResume()方法时,会启动服务。正常情况下,MainService开始执行onCreate()方法。此方法里,启动线程,因为我的MainService是实现了Runnbale接口的。

    View Code
    public class MainService extends Service implements Runnable {
               。。。
            // 循环控制变量
            private boolean isrun = true;
               。。。
        
            @Override
               public void onCreate() {
        super.onCreate();
        isrun = true;
        new Thread(this).start();
               }
        
    }        

    3.于是,后台服务框架正常搭建起来了。子线程一直在获取任务,只要有任务的时候,取走任务,然后就执行任务。

      run方法:

    View Code
    /*********
         * 启动线程
         */
        @Override
        public void run() {
            while (isrun) {
                Task lastTask = null;
                if (allTasks.size() > 0) {
                    synchronized (allTasks) {
                        // 获取任务
                        lastTask = allTasks.get(0);
                        // 执行任务
                        doTask(lastTask);
                    }
                }
                // 如果没有任务,则等待2000ms,继续获取任务
                try {
                    Thread.sleep(2000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
        }

    4.插叙一下Handler。

      在每个Acitivity和Service主线程下,有一个Handler对象负责线程通信,消息传递,更新UI。(我是这么理解的)。通常采用异步实现网络通信,通过Handler来做数据媒介,然后把数据显示在界面上来。

      主要涉及Message对象和handMessage(Message msg)方法。有时候还常用Handler对象的postXXX(Runnable run)方法。此方法有几个重载方法。就是加入一个Runnable(api:Represents a command that can be executed,表示可执行的命令)到Handler对象的附属子线程队列里。

    5.理一下doTask(Task task)方法。

      5.1先瞧瞧系统要执行的任务Task

      

    View Code
    package com.mpros.bean;
    
    import java.util.Map;
    
    /**
     * 任务类 获取不同信息
     * 
     * @author Scherrer
     * 
     */
    public class Task {
    
        // 任务编号
        public static final int TASK_GET_PRODUCTTYPE = 0;// 获取产品类别
        public static final int GET_TYPE_LOGO = 1; // 获取父类logo
    
        public static final int TASK_GET_CHILDTYPE_LOGO = 2;// 获取二级类别logo
    
        public static final int TASK_GET_PRODUCT_IMAGE = 3;// 获取产品
    
        // 日志
        public static final String Logger = "logger";
    
        private int taskId;// 任务编号
        @SuppressWarnings("rawtypes")
        private Map taskParam;// 任务参数
    
        @SuppressWarnings("rawtypes")
        public Task(int taskId, Map taskParam) {
            this.taskId = taskId;
            this.taskParam = taskParam;
        }
    
        public int getTaskId() {
            return taskId;
        }
    
        public void setTaskId(int taskId) {
            this.taskId = taskId;
        }
    
        @SuppressWarnings("rawtypes")
        public Map getTaskParam() {
            return taskParam;
        }
    
        @SuppressWarnings("rawtypes")
        public void setTaskParam(Map taskParam) {
            this.taskParam = taskParam;
        }
    }

      这里我声明成了原生类型了,但在Java里,在使用HashMap或者Map,常常会涉及泛型,如:Map<?,?> map ;

      5.2 首先创建一个消息对象

      Message msg = new Message();

      5.3 赋予消息的标识,这里把任务编号赋予它。

      msg.what = task.getTaskId();

      5.4 通过switch语句,根据任务ID分别执行任务。具体代码上文已贴了。

    6.在点击获取产品分类时,会转至相应分类的Activity。在初始化方法里,老规矩先检查网络,然后新建任务,该任务表示获取产品分类。

    View Code
    @Override
        public void init() {
            // 网络正常,新建获取产品类别的任务
            if (NetUtil.checkNet(this)) {
                Task getTypeTask = new Task(Task.TASK_GET_PRODUCTTYPE, null);
                MainService.newTask(getTypeTask);
                // 将此activity入栈
                MainService.allActivities.add(this);
            } else {
                MainService.alerNetErr(this);
            }
        }

    7.MainService会马上收到任务,然后调用doTask方法。根据编号,执行获取产品分类任务。

    View Code
    Message msg = new Message();
            System.out.println("任务编号: " + task.getTaskId());
            msg.what = task.getTaskId();
            try {
                switch (task.getTaskId()) {
    
                case Task.TASK_GET_PRODUCTTYPE:// 获取产品类型

    8.封装通过Http获取请求响应(HttpResponse)以及通过一个图片的URL,然后返回一张位图(BitmapDrawable)的工具类HttpUtil.

    View Code
    package com.mpros.util;
    
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.impl.client.DefaultHttpClient;
    
    import android.graphics.drawable.BitmapDrawable;
    
    public class HttpUtil {
    
        public static HttpResponse getHttpResponse(String url)
                throws ClientProtocolException, IOException {
    
            // post请求
            HttpPost post = new HttpPost(url);
            // 请求客户
            DefaultHttpClient client = new DefaultHttpClient();
            return client.execute(post);
        }
    
        /***
         * 获取logo
         * 
         * @param url
         * @return
         */
        public static BitmapDrawable getImageFromUrl(String action) {
            BitmapDrawable icon = null;
            try {
    
                URL url = new URL(action);
                HttpURLConnection hc = (HttpURLConnection) url.openConnection();
                icon = new BitmapDrawable(hc.getInputStream());
                hc.disconnect();
            } catch (Exception e) {
            }
            return icon;
    
        }
    }

    9.解析json数据的业务。

      通过HttpUtil获取一个HttpResponse.

      HttpResponse response = HttpUtil.getHttpResponse(action);//在浏览器里输入此action,浏览器里可显示一串json数据。

      测试响应码

      // 响应code
        int rescode = response.getStatusLine().getStatusCode();如果rescode 为200,表示获取ok.

      然后通过response.getEntity().getContent();方法返回获取的所有数据,在转化为StringBuffer变长字串。再根据字段来解析。

    View Code
    package com.mpros.service.json;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.http.HttpResponse;
    import org.json.JSONArray;
    import org.json.JSONObject;
    
    import android.util.Log;
    
    import com.mpros.bean.Task;
    import com.mpros.bean.product.Product;
    import com.mpros.bean.product.ProductBrand;
    import com.mpros.bean.product.ProductStyle;
    import com.mpros.bean.product.ProductType;
    import com.mpros.bean.product.Sex;
    import com.mpros.util.HttpUtil;
    
    /***
     * 产品模块 解析json数据
     * 
     * @author Scherrer
     * 
     */
    public class ProductTypeService {
    
        /**
         * 获取产品类型
         * 
         * @param action
         *            访问URl
         * @return 类型列表
         */
        public static List<ProductType> getTypesFromJson(String action) {
    
            List<ProductType> types = null;
            try {
                HttpResponse response = HttpUtil.getHttpResponse(action);
                // 响应code
                int rescode = response.getStatusLine().getStatusCode();
                if (rescode == 200) {// 获取ok
                    String line = null;
                    StringBuilder builder = new StringBuilder();// 可变String
                    BufferedReader lineReader = new BufferedReader(
                            new InputStreamReader(response.getEntity().getContent()));
    
                    while ((line = lineReader.readLine()) != null) {
                        builder.append(line);
                    }
    
                    Log.i(Task.Logger, builder.toString());
                    JSONObject obj = new JSONObject(builder.toString());
                    obj = obj.getJSONObject("types");
                    // 以关键字types获取一个json数组
                    JSONArray array = obj.getJSONArray("results");
    
                    // /System.out.println("json array " + array.toString());
                    types = new ArrayList<ProductType>();
    
                    JSONObject temp = null;
                    for (int i = 0; i < array.length(); ++i) {
                        temp = (JSONObject) array.opt(i);
                        System.out.println("temp i" + temp.toString());
                        ProductType type = resolveProductType(temp);
    
                        // 是否有子类
                        if (temp.getString("childTypes") != null) {
    
                            JSONArray array2 = temp.getJSONArray("childTypes");
    
                            System.out.println("获取的子类数组 -- " + array2.toString());
                            List<ProductType> childtypes = new ArrayList<ProductType>();
    
                            for (int e = 0; e < array2.length(); ++e) {
    
                                JSONObject temp2 = (JSONObject) array2.opt(e);
                                System.out.println("二级类别 一条记录 ---- " +
                                 temp2.toString());
                                ProductType childtype = resolveProduct(temp2);
    
                                if (temp.getString("childTypes") != null) {
                                    JSONArray array3 = temp
                                            .getJSONArray("childTypes");
                                    List<ProductType> child2types = new ArrayList<ProductType>();
                                    for (int k = 0; k < array3.length(); ++k) {
    
                                        JSONObject temp3 = (JSONObject) array3
                                                .opt(k);
                                         System.out.println("temp3 k" +
                                         temp3.toString());
                                        child2types.add(resolveProduct(temp3));
                                    }
                                    childtype.setChildtypes(child2types);
                                }
                                if(childtype != null) {
                                    childtypes.add(childtype);
                                }
                                
                            }
                            type.setChildtypes(childtypes);
                        }
    
                        if (type != null) {
                            types.add(type);
                        }
                        
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
    
            Log.i(Task.Logger, "types --- 大小" + types.size());
            for (ProductType type : types) {
                if (type.getChildtypes() != null) {
                    Log.i(Task.Logger, "type child types --- 大小"
                            + type.getChildtypes().size());
                }
            }
    
            return types != null ? types : null;
        }
    
        public static ProductType resolveProduct(JSONObject temp) {
    
            ProductType type = new ProductType();
            try {
                // 获取type的简单属性
                System.out.println("产品类型属性:");
                type.setTypeid(Integer.parseInt(temp.getString("typeId")));
    
                System.out.println("typeid: "
                        + Integer.parseInt(temp.getString("typeId")));
    
                type.setName(temp.getString("name"));
                System.out.println("type name -- " + temp.getString("name"));
    
                type.setRemark(temp.getString("remark"));
                System.out.println("type remark -- " + temp.getString("remark"));
                
                type.setTypelogo(temp.getString("typelogo"));
                
    
                JSONArray products = temp.getJSONArray("products");
    
                if (products != null) {
                    
                    System.out.println("类别产品  -- " + products.toString());
                    // 获取type的所有产品--产品列表
                    for (int j = 0; j < products.length(); ++j) {
                        JSONObject p = (JSONObject) products.opt(j);
                        Product product = new Product();
                        System.out.println("一个产品记录 -- " + p.toString());
                        // 产品简单属性
                        
                        System.out.println("产品id-- " + p.getInt("id"));
                        product.setId(p.getInt("id"));
                        
                        product.setCode(p.getString("code"));
                        System.out.println("产品货号: " + p.getString("code"));
                        
                        product.setBaseprice(Float.parseFloat(p
                                .getString("baseprice")));
                        if (p.getString("buyexplain") != null) {
                            product.setBuyexplain(p.getString("buyexplain"));
                        }
                        
                        product.setClickcount(p.getInt("clickcount"));
                        product.setCommend(p.getBoolean("commend"));
                        product.setCreatetime(p.getString("createdate"));
                        product.setDescription(p.getString("description"));
                        product.setMarketprice(Float.parseFloat(p
                                .getString("marketprice")));
                        
                        if(p.getString("model") != null) {
                            product.setModel(p.getString("model"));
                        }
                        
                        product.setName(p.getString("name"));
                        product.setSellcount(p.getInt("sellcount"));
                        product.setSellprice(Float.parseFloat(p
                                .getString("sellprice")));
                        product.setSexrequest(Sex.valueOf(p.getString("sexrequest")));
                        
                        System.out.println("产品性别要求 -- " + product.getSexrequest());
                        
                        /*if (p.getString("weight") != null) {
                            product.setWeight(Integer.parseInt(p.getString("weight")));
                        }*/
                        System.out.println(" 产品品牌 测试 ---------");
                        
                        // 品牌
                        /*if (p.getString("brand") != null) {
                            JSONObject b = p.getJSONObject("brand");
                            System.out.println("产品品牌记录 -- " + b.toString());
                            ProductBrand brand = new ProductBrand();
                            brand.setId(b.getString("id"));
                            brand.setLogoPath(b.getString("logoPath"));
                            brand.setName(b.getString("name"));
                            // 产品添加品牌
                            product.setBrand(brand);
                        }*/
    
                        System.out.println(" 产品样式  测试 ---------");
                        if (p.getJSONArray("styles") != null) {
                            // 产品样式
                            JSONArray ss = p.getJSONArray("styles");
                            System.out.println("产品样式记录 -- " + ss.toString());
                            for (int k = 0; k < ss.length(); ++k) {
                                JSONObject s = (JSONObject) ss.opt(k);
                                System.out.println("一条样式记录 -- " + s.toString());
                                ProductStyle style = new ProductStyle();
                                style.setId(s.getInt("id"));
                                style.setName(s.getString("name"));
                                style.setImagename(s.getString("imagename"));
                                // 添加样式
                                product.addStyle(style);
                            }
                        }
    
                        // 添加产品
                        type.addProduct(product);
                    }
                }
    
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
    
            return type;
        }
        
        /***
         * 解析产品类型
         * @return
         */
        public static ProductType resolveProductType(JSONObject temp) {
            
            ProductType type = new ProductType();
            try {
                // 获取type的简单属性
                System.out.println("产品类型属性:");
                type.setTypeid(Integer.parseInt(temp.getString("typeId")));
    
                System.out.println("typeid: "
                        + Integer.parseInt(temp.getString("typeId")));
    
                type.setName(temp.getString("name"));
                System.out.println("type name -- " + temp.getString("name"));
    
                type.setRemark(temp.getString("remark"));
                System.out.println("type remark -- " + temp.getString("remark"));
                
                type.setTypelogo(temp.getString("typelogo"));
                System.out.println("type logo -- " + temp.getString("typelogo"));
    
            }catch (Exception e) {
                e.printStackTrace();
                return null;
            }
            return type;
        }
    }

    10.在执行获取产品类型时,正常的话会返回解析好的产品类型对象列表list。然后通过handler对象传递该list,根据任务id去更新UI。

    View Code
            msg.obj = types;    
                        。。。
            handler.sendMessage(msg);
        allTasks.remove(task);// 执行完任务,则移出该任务
    
    
    
    
    
        // 当前服务的子线程Handler,负责处理更新UI操作
        private Handler handler = new Handler() {
            
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.i(Task.Logger, "UI 更新编号:" + msg.what);
                switch (msg.what) {
    
                case Task.TASK_GET_PRODUCTTYPE:
    
                    IMActivity ia = (ClassifyActivity) getActivityByName("ClassifyActivity");
                    ia.refresh(ClassifyActivity.GET_TYPE_SUCCESS, msg.obj);

    11.在ClassifyActivity里实现refresh方法。

      

    View Code
    @SuppressWarnings("unchecked")
        @Override
        public void refresh(Object... param) {
            switch (((Integer) param[0]).intValue()) {
            case GET_TYPE_SUCCESS:
                viewBar.setVisibility(View.GONE);
                List<ProductType> producttypes = (List<ProductType>) param[1];
                this.types = producttypes;
                if (this.types != null) {
                    System.out.println("获取的类别记录 -- " + this.types.size());
                    Log.i(Task.Logger, "types.size() -- " + this.types.size());
                    // 适配器
                    MyListViewAdapter adapter = new MyListViewAdapter(this, this.types);
                    typesListView.setAdapter(adapter);
                } else {
                    makeToast("加载数据失败,请再试..");
                }
    
                break;

    12.执行一个任务的逻辑顺序就是这样了,

      通过UI新建任务  ---> 后台服务获取任务并执行任务 ---> 通过相应的方法获取的数据 ---> Hanlder传递数据 ---> 返回原来的UI ---> UI是否更新.

    有时间会再补充我觉得比较有用的UI设计。

      

        

  • 相关阅读:
    第12组 Beta冲刺 (4/5)
    第12组 Beta冲刺 (3/5)
    代码用辅助多了 基础的读取config都忘记了
    wpf 动态添加控件 通过xmal实习 c#代码插入控件
    C#里调用非托管的Dll -z注意 net版本
    动态调用 类库
    c#时间的生成
    c# 第三方 修改版本号 MSBuildTasks, 解决 通配符不匹配问题
    c#.exe以管理员身份运行
    log4
  • 原文地址:https://www.cnblogs.com/scherrer/p/2948791.html
Copyright © 2011-2022 走看看