Android数据解析之JSON,网络编程之URL,异步任务AsyncTask讲解

工作内容:

1.网络编程之URL

2.JSON数据解析

3.异步任务

学习分享:

一、网络编程之URL;(用于请求服务器,获取到JSON字符串)

主要遇到的是:请求数据的方式 POST,GET的差异

GET  :少量数据,请求参数跟在请求网址后面 — 不安全
POST :大量数据,请求参数放在请求的正文里 — 相对安全些,可以携带数据存入服务器

二、JSON数据解析(JSON字符串解析)

主要步骤:

1.请求服务器(返回一个JSON字符串)

2.将JSON字符串解析成一个一个的对象(可以JSON数据中的键看作是属性,值就是对应的属性值)

JSON字符串解析:

1.获取最外层的JSONObject object = new JSONObject(JSON字符串)

2.逐层解析,遇到“{}”表示是一个JSONObject ,遇到“[]”,表示是一个JSONArray(JSON数组)

常用方法:

JSONObject.getJSONObject(String key)//用于对象下面一层还是对象的情况

JSONArray array = JSONObject.getJSONArray(String key)//用于对象下面是数组的情况

for(int i=0;i<array.length(),i++)

JSONObject object = array.get(i)//i表示数组下标//获取JSONArray数组中的JSONObject

String str = array.getString(i)//数组中的数据是一个字符串数组【用JSONArray去获取,不能用String[]去获取】,在去遍历array中的字符串

三、异步任务(异步任务泛型类AsyncTask)

唤起异步任务:new NewsShowAsyncTask().execute(URLString)//生成异步类对象,并调用execute()执行异步任务(这里只传入了一个参数【是可以传入很多参数的】)

1.异步任务执行顺序

准备步:(UI中执行)

protected void onPreExecute(){ ... }

第二步:后台执行的方法(非Ui中执行)

protectedList<info> doInBackground(String ... parms){ //参数说明:可以变参数(可以传入一组/多个参数)

 List<info> infos = getInfos(parms[0]);//调用耗时方法,如果子传入了一个参数则这里的parms[0]就是那个参数

return  info;

}

第三步:(Ui中执行)//设置进度(与后台任务同步执行)

protected void onProgressUpdate(Integer...params){ ...  }

第四步:Ui中执行(后台任务执行完成后执行)

protected void onPostExecute( List<info> infos ){

super.onPostExecute(infos);

}

【注意:打断异步任务,可以在onStop()方法中用异步对象调用cancel(true)表示允许在异步任务执行过程中被打断,再在doInBackground中调用if(isCancelled){retrun}允许执行过程中被打断,则直接return null结束此方法执行】

代码演示:

Activity代码(异步任务类)(需修改:填入自己申请的apikey)(数据源于“阿凡达”api数据,国内新闻和时事新闻)

import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.plane.people.planebattle.adapter.NewsShowRecyAdapter;
import com.plane.people.planebattle.base.RecylerItemClickListener;
import com.plane.people.planebattle.obj.NewsContent;
import com.plane.people.planebattle.tool.InputUtil;
import com.plane.people.planebattle.url.GetObjFromJSONUtil;
import java.util.ArrayList;
import java.util.List;

public class NewsShowActivity extends AppCompatActivity implements View.OnClickListener,RecylerItemClickListener{
    private String searchInfo = ""; //接收上一个界面传过来的搜索条件
    private Toolbar toolbar;
    private RecyclerView recyclerView;
    private ImageView imageView; //搜索图标
    private EditText editText;   //搜索栏的输入框
    private NewsShowRecyAdapter adapter;
    private List<NewsContent> list;
    private String url = "http://api.avatardata.cn/ActNews/Query?key=填入自己申请的apikey&keyword=";
    private String urlString = "";  //请求json数据的网址和请求参数组成的字符串
    private ProgressBar progressBar;//异步任务执行完成后圆形进度条消失(隐藏和gone都可以)
    //判断是否搜索到数据,没搜索到就会进行第二次搜索,最后以此弹出消息提醒用户“未搜索到相关信息”
    private boolean isFailure = false;
    private NewsShowAsyncTask newsShowAsyncTask;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_news_show);
        initView();
        initData();
    }

    private void initView() {
        list = new ArrayList<>();
        recyclerView = (RecyclerView)findViewById(R.id.rv_nsa);
        progressBar = (ProgressBar)findViewById(R.id.pb_nsa);
        imageView = (ImageView)findViewById(R.id.iv_layout_searline_summer);
        editText = (EditText)findViewById(R.id.et_layout_searline_summer);
        InputUtil.setInputKeyboardDisappear(this,editText); //输入键盘消失
        //设置标题栏toolbar
        toolbar = (Toolbar)findViewById(R.id.toolbar_news_show);
        toolbar.setTitle("新闻搜索");
        toolbar.setTitleTextColor(Color.WHITE);
        toolbar.setNavigationIcon(R.drawable.back);
        setSupportActionBar(toolbar);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        imageView.setOnClickListener(this);//添加搜索点击事件
        //设置recyclerView
        adapter = new NewsShowRecyAdapter(list);
        LinearLayoutManager manager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
        recyclerView.setLayoutManager(manager);
        recyclerView.setAdapter(adapter);
        adapter.setRecylerItemClickListener(this);
    }

    private void initData() {
        newsShowAsyncTask = new NewsShowAsyncTask();//生成异步任务类对象
        //获取从上一个界面传过来的搜索条件
        Intent intent = this.getIntent();
        if(intent != null){
            searchInfo = intent.getStringExtra("searchinfo");
        }
        urlString =  url+searchInfo;
        /**
         * 执行异步任务
         * 传入一个参数
         */
        new NewsShowAsyncTask().execute(urlString);
    }
    //点击搜索事件
    @Override
    public void onClick(View v) {
        searchInfo = editText.getText().toString();
        //判断用户有无填入搜索内容
        if(searchInfo.length()!=0) {
            progressBar.setVisibility(View.VISIBLE);
            urlString = url + searchInfo;
            new NewsShowAsyncTask().execute(urlString);//唤起异步任务类,并传入参数
            editText.clearFocus();
            InputUtil.setInputKeyboardDisappear(this, editText);
        }else{
            Toast.makeText(this,"请输入新闻内容",Toast.LENGTH_SHORT).show();
        }
    }
    //点击事件,打开网页
    @Override
    public void onRecylerItemClick(View view, int position) {
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(list.get(position).getUrlString()));
        startActivity(intent);
    }

    /**
     *  异步任务类(泛型)
     *  parmas 泛型参数类型(new NewsShowAsyncTask().execute(urlString);)urlString的类型
     *  progress 表示进度的值类型
     *  result 返回值类型
     */
    class NewsShowAsyncTask extends AsyncTask<String,Integer,List<NewsContent>> {
        @Override
        protected List<NewsContent> doInBackground(String... params) {
            List<NewsContent> newsContents = null;
            //后台去找数据
            if(isCancelled()){//假如允许在执行过程中被打断
                return null;
            }else{
                newsContents = GetObjFromJSONUtil.getNewsContent(params[0]);
                if (newsContents.size()==0){//如果没找到数据,去找国内新闻来填充空白
                    isFailure = true;   //判断是否进行过2次加载
                    String url = "http://api.avatardata.cn/GuoNeiNews/Query?key=填入自己申请的apikey&page=1&rows=50";
                    newsContents = GetObjFromJSONUtil.getInChinaNewsContent(url);
                }
            }
            return newsContents;
        }
        /**
         * UI线程执行,后台执行完成后执行
         * 回调函数
         * newsContents是后台执行完成后返回的数据
         * 在这里直接用
         */
        @Override
        protected void onPostExecute(List<NewsContent> newsContents) {
            super.onPostExecute(newsContents);
            list.clear();//清除list中的数据
            list.addAll(newsContents);
            adapter.notifyDataSetChanged();
            progressBar.setVisibility(View.INVISIBLE);
            //判断是否进行了2次搜索
            if(isFailure){
                Toast.makeText(NewsShowActivity.this,"未搜索到相关内容",Toast.LENGTH_SHORT).show();
                isFailure = false;
            }
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        //设置允许在(异步任务正在执行中打断其继续执行)
        newsShowAsyncTask.cancel(true);
    }
}
请求JSON数据

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by Administrator on 2016/9/9.
 */
public class JSONUtil {
    private JSONUtil(){}   //不允许创建对象
    /**
     * @param UrlString 请求服务器网址+参数(网址?参数)
     * @return 返回结果
     */
    public static String request(String UrlString) {
        BufferedReader reader = null;
        String result = null;
        StringBuffer sbf = new StringBuffer();
        try {//生成URL对象
            URL url = new URL(UrlString);
            //建立连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);//设置读取
            /**
             * 请求方式 GET POST
             * GET  :少量数据,请求参数跟在请求网址后面 — 不安全
             * POST :大量数据,请求参数放在请求的正文里 — 相对安全些,可以携带数据存入服务器
             */
            connection.setRequestMethod("GET");
            // 填入apikey到HTTP header
            connection.setRequestProperty("apikey", "1b003ee9be62dfbef84e61ff07f54bc2");
            connection.connect();//连接
            InputStream is = connection.getInputStream();//获取返回的流
            reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));//转化成字符缓冲流
            String strRead = null;
            while ((strRead = reader.readLine()) != null) {
                sbf.append(strRead);//将读取到的Json字符串放入sbf中
                sbf.append("\r\n");//换行
            }
            reader.close();//关闭流
            connection.disconnect();//关闭连接
            result = sbf.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
解析JSON数据

/**
     * 解析Json字符串(搜索国内新闻)
     * @param urlString Json字符串
     * @return
     */
    public static List<NewsContent> getInChinaNewsContent(String urlString){
        List<NewsContent> list = new ArrayList<>();//返回的list初始化
        String jsonString = JSONUtil.request(urlString);
        try {
            JSONObject jsonObject = new JSONObject(jsonString);//获取最外层的JSONObject
            //判断是否连接成功
            if ("Succes".equals(jsonObject.getString("reason"))) {
//                Log.e("***国内新闻***", "获取到数据"+jsonObject.toString());
                //获取第二层的字符串数组
                JSONArray array = jsonObject.getJSONArray("result");
                for (int i = 0; i < array.length(); i++) {
                    JSONObject jsonObj = array.getJSONObject(i);
                    String title = jsonObj.getString("title");
                    String src = "国内新闻";
                    String pdate_src = jsonObj.getString("ctime");
                    String content = jsonObj.getString("description");
                    String img = jsonObj.getString("picUrl");
                    String url = jsonObj.getString("url");
                    Bitmap bitmap = null;
                    if(img != null && img != ""){
                        //调用方法将网络图片转化成bitmap
                        bitmap = CreateBitmapFromUrl.CreateBitmap(img);
                    }
                    list.add(new NewsContent(title,content,src,url,pdate_src,bitmap));
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return list;
    }
}
最后附加一个Activity的xml代码

<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    tools:context="com.plane.people.planebattle.NewsShowActivity">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar_news_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/darkturquoise"
        app:popupTheme="@style/OverflowMenuStyle"/>
    <include layout="@layout/layout_searchline_summer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        >
        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/rv_nsa">
        </android.support.v7.widget.RecyclerView>
        <ProgressBar
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerInParent="true"
            style="@style/Widget.AppCompat.ProgressBar"
            android:id="@+id/pb_nsa"
            />
    </RelativeLayout>
</LinearLayout>

Aapter代码:

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.plane.people.planebattle.R;
import com.plane.people.planebattle.base.RecylerItemClickListener;
import com.plane.people.planebattle.obj.NewsContent;
import java.util.List;

/**
 * Created by Administrator on 2016/9/11.
 */
public class NewsShowRecyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
    private List<NewsContent> list;
    /**
     * 设置监听Recyler列表项的监听事件
     * (自定的一个接口,就一个方法:void onRecylerItemClick(View v,int position))
     */
    public void setRecylerItemClickListener(RecylerItemClickListener recylerItemClickListener) {
        this.recylerItemClickListener = recylerItemClickListener;
    }

    private RecylerItemClickListener recylerItemClickListener;
    public NewsShowRecyAdapter(List<NewsContent> list) {
        this.list = list;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_newscontent,parent,false);
        ViewHolder_newsContent holder_newsContent = new ViewHolder_newsContent(view);
        return holder_newsContent;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder,final int position) {
        ViewHolder_newsContent myHolder = (ViewHolder_newsContent)holder;
        if(list.get(position).getBitmap()!=null){
            myHolder.imageView.setImageBitmap(list.get(position).getBitmap());
        }else{
            myHolder.imageView.setVisibility(View.GONE);
        }
        myHolder.tvTitle.setText(list.get(position).getTitle());
        myHolder.tvSrcTime.setText("来源:" + list.get(position).getSrc() + " 发布时间:" +
                list.get(position).getPdate_src());
        myHolder.tvContent.setText(list.get(position).getContent());
        myHolder.linearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //点击列表项调用自定义接口中的回调方法(activity中实现)
                recylerItemClickListener.onRecylerItemClick(v,position);
            }
        });
    }

    @Override
    public int getItemCount() {
        return list.size();
    }
    class ViewHolder_newsContent extends RecyclerView.ViewHolder{
        TextView tvTitle,tvSrcTime,tvContent;
        ImageView imageView;
        LinearLayout linearLayout;
        public ViewHolder_newsContent(View itemView) {
            super(itemView);
            imageView = (ImageView)itemView.findViewById(R.id.iv_item_newscontent);
            tvTitle = (TextView)itemView.findViewById(R.id.tv_title_item_newscontent);
            tvSrcTime = (TextView)itemView.findViewById(R.id.tv_src_time_item_newscontent);
            tvContent = (TextView)itemView.findViewById(R.id.tv_content_item_newscontent);
            linearLayout = (LinearLayout)itemView.findViewById(R.id.linear_item_newscontent);
        }
    }
}

网络图片转换成Bitmap代码:

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by Administrator on 2016/9/9.
 */
public class CreateBitmapFromUrl {
    private CreateBitmapFromUrl(){}//不允许生成对象
    /**
     * 将图片资源转换为bitmap
     * @param imageUrl
     * @return
     */
    public static Bitmap CreateBitmap(String imageUrl){
        Bitmap bitmap = null;
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setReadTimeout(5000);
            connection.setDoInput(true);
            connection.connect();
            bitmap = BitmapFactory.decodeStream(connection.getInputStream());
            connection.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;
    }
}

显示效果:(获取到图片则显示出来,没图片则)让ImageView的可见性=gone


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值