在Android中使用AsyncTask获取JSON

4
我将尝试使用AsyncTask获取JSON,因为我在logcat中看到了以下信息:AndroidRuntime(18153): Caused by: android.os.NetworkOnMainThreadException
以下是我的代码:
public class LatestAlbums extends Activity {

    TextView t;

    // url to make request
    private static String url = "www.example.com";

    // JSON Node names
    private static final String TAG_ALBUMS = "albums";
    private static final String TAG_ID = "id";
    private static final String TAG_NAME = "name";
    private static final String TAG_SINGER = "singer";
    private static final String TAG_GENRE = "genre";
    private static final String TAG_MIX = "mix";
    private static final String TAG_THUMB = "thumb";
    private static final String TAG_SONGS = "songs";
    private static final String TAG_SONG_TITLE = "song";
    private static final String TAG_SONG_ARTIST = "artist";
    private static final String TAG_SONG_MP3 = "mp3";
    private static final String TAG_SONG_MP4 = "mp4";
    private static final String TAG_SONG_THUMB = "thumb";

    // albums JSONArray
    JSONArray albums = null;
    JSONArray sngs = null;
    JSONObject objects = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.favorites);
        t = (TextView) findViewById(R.id.json);
        loadJSON();
    }

    public void loadJSON() {
        // Creating JSON Parser instance
        JSONParser jParser = new JSONParser();

        // getting JSON string from URL
        JSONObject json = jParser.getJSONFromUrl(url);

        try {
            // Getting Array of albums

            albums = json.getJSONArray(TAG_ALBUMS);
            sngs=json.getJSONArray(TAG_SONGS);
            // looping through All albums
            for (int i = 0; i < albums.length(); i++) {
                JSONObject c = albums.getJSONObject(i);

                // Storing each json item in variable
                String album_id = c.getString(TAG_ID);
                String album_name = c.getString(TAG_NAME);
                String album_singer = c.getString(TAG_SINGER);
                String album_genre = c.getString(TAG_GENRE);
                String album_thumb = c.getString(TAG_THUMB);

                // songs are again JSON Object
                for (int j = 0; i < sngs.length(); j++) {
                    JSONObject s = sngs.getJSONObject(j);
                    JSONObject songs = s.getJSONObject(TAG_SONGS);
                    String artist = s.getString(TAG_SONG_ARTIST);
                    String mp3 = s.getString(TAG_SONG_MP3);
                    String mp4 = s.getString(TAG_SONG_MP4);
                    String song_thumb = s.getString(TAG_SONG_THUMB);
                    String song_title = s.getString(TAG_SONG_TITLE);
                }
                Log.v("--", "Albums \n" + " " + album_id + " " + album_name
                        + " " + album_genre + " " + album_singer + " "
                        + album_thumb);
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

}

请问有人可以告诉我如何做到这一点吗?

(涉及IT技术)
3个回答

10

阅读JSON并将其设置到适配器的最佳且简单的方法。

AsyncTask有三种方法。

PreExecute和PostExecute中,您可以设置任何视图属性(因为您在主UI线程上),但是在doInBackground中(执行不涉及与UI交互的操作)它会读取JSON。

package com.example.tabs;

import java.util.ArrayList;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;

import com.example.adapters.CalendarAdapter;
import com.example.description.CalendarDescription;

public class Calendar extends Activity {

    String url = "Enter your URL here ";

    GetData data;

    ProgressDialog progressDialog;

    ListView list_of_calendar;

    ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.calendar);

        list_of_calendar = (ListView) findViewById(R.id.list_of_calendar);

        new GetData().execute();
        //new GetData(url).execute();//you can pass it like this and see comment in doInBackground

        //ListView listView = getListView();
        list_of_calendar.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) 
            {
                HashMap<String, String> map = list.get(position);               

                Intent intent = new Intent(Calendar.this, CalendarDescription.class);

                intent.putExtra("name", map.get("name"));

                intent.putExtra("date", map.get("date"));

                intent.putExtra("description", map.get("description"));

                startActivity(intent);


            }

        });
    }

    private class GetData extends AsyncTask<String, Void, JSONObject> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            progressDialog = ProgressDialog.show(Calendar.this,
                    "", "");

        }

        @Override
        protected JSONObject doInBackground(String... params) {

            String response;

            try {

                HttpClient httpclient = new DefaultHttpClient();

                HttpPost httppost = new HttpPost(url);
                //HttpPost httppost = new HttpPost(params[0]);//you can also pass it and get the Url here. 

                HttpResponse responce = httpclient.execute(httppost);

                HttpEntity httpEntity = responce.getEntity();

                response = EntityUtils.toString(httpEntity);

                Log.d("response is", response);

                return new JSONObject(response);

            } catch (Exception ex) {

                ex.printStackTrace();

            }

            return null;
        }

        @Override
        protected void onPostExecute(JSONObject result) 
        {
            super.onPostExecute(result);

            progressDialog.dismiss();

            if(result != null)
            {
                try
                {
                    JSONObject jobj = result.getJSONObject("result");

                    String status = jobj.getString("status");

                    if(status.equals("true"))
                    {
                        JSONArray array = jobj.getJSONArray("data");

                        for(int x = 0; x < array.length(); x++)
                        {
                            HashMap<String, String> map = new HashMap<String, String>();

                            map.put("name", array.getJSONObject(x).getString("name"));

                            map.put("date", array.getJSONObject(x).getString("date"));

                            map.put("description", array.getJSONObject(x).getString("description"));

                            list.add(map);
                        }

                        CalendarAdapter adapter = new CalendarAdapter(Calendar.this, list);

                        list_of_calendar.setAdapter(adapter);
                    }
                }
                catch (Exception e) 
                {
                    e.printStackTrace();
                }
            }
            else
            {
                Toast.makeText(Calendar.this, "Network Problem", Toast.LENGTH_LONG).show();
            }
        }

    }
}

编辑

这段代码是针对网址的。

http://www.socialgeolocate.com/DayCare/webservices/Get_calender.php?


那个解析的JSON结构的例子是什么?我不理解“result”,“status”和“data”这些字符串。谢谢。 - Karlo A. López
Karlo,请看我的更新答案。我已经附上了获取数据的链接。 - Zar E Ahmer
1
谢谢nepster,我有一个疑问,如何获取一个干净的JSON数组(我的意思是,在之前没有字典或JSONObject),但现在我知道我应该在整个asyncTask中使用JSONArray而不是JSONObject,这就是为什么我想看看那个读取的JSON,再次感谢。 - Karlo A. López
你的示例URL只返回text/html格式的内容,为什么不使用application/json MIME类型来返回内容呢? - jap1968
现在我无法访问它。但是您可以通过添加Google Chrome的JSONView插件来查看JSON。 - Zar E Ahmer

5

在后台加载您的JSON对象(执行网络操作),并在UI线程中处理结果,即:

URL requestUrl = "...";

new AsyncTask<URL, Void, JSONObject>() {

    @Override
    protected Boolean doInBackground(URL... urls) {
        loadJSON(url);
    }

    @Override
    protected void onPostExecute(JSONObject jsonData) {
        try {
            // Getting Array of albums

            albums = json.getJSONArray(TAG_ALBUMS);
            sngs=json.getJSONArray(TAG_SONGS);
            // looping through All albums

            etc.
    }
}.execute(requestUrl);


public void loadJSON(URL url) {
    // Creating JSON Parser instance
    JSONParser jParser = new JSONParser();

    // getting JSON string from URL
    JSONObject json = jParser.getJSONFromUrl(url);

    return json;
}

查看此链接以获取更多信息。

干杯!


当我把它放入我的代码中时,出现了许多错误。我需要把它放在一个新类中吗? - Darko Petkovski
1
我只是试图给你一个大致的想法。当然还有一些事情要做。但是这个想法应该很清楚,不是吗?附注:如果你在某个地方卡住了,请粘贴你更新后的代码并说明哪里出了问题。 - Trinimon
1
@BozidarPrcovski,你有没有在developers.android.com上读过关于ASyncTask的内容?如果是这样的话,在实现它的时候就不应该有任何问题了。 - Arslan Ali

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接