从JSON中的服务器获取数据并解析它

时间:2016-03-24 12:34:47

标签: java android json xml

我正在开发和Android应用程序,从服务器获取图像并下载它们并将它们插入GridView布局。 我从中获取数据的服务器是电影数据库https://www.themoviedb.org/ 假设发送具有特定URL的服务器为http://api.themoviedb.org/3/movie/popular?api_key=2add2d45d1265781502d4d7c2f9f67c2 将使服务器向我发送最流行电影的海报(图像)流,然后我将解析JSON响应并在网格视图中显示图像 这是我的文件.... 1)MainActivity.java

public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private GridView mGridView;
private ProgressBar mProgressBar;
private ImageAdapter mGridAdapter;
private ArrayList<GridItem> mGridData;
private String FEED_URL = "http://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=2add2d45d1265781502d4d7c2f9f67c2";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mGridView = (GridView) findViewById(R.id.grid_view);
    mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
    mGridData = new ArrayList();
    mGridAdapter = new ImageAdapter(this, R.layout.grid_item, mGridData);
    mGridView.setAdapter(mGridAdapter);

    //Start download
    new AsyncHttpTask().execute(FEED_URL);
    mProgressBar.setVisibility(View.VISIBLE);

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

//Downloading data asynchronously
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {

    @Override
    protected Integer doInBackground(String... params) {
        Integer result = 0;
        try {
            // Create Apache HttpClient
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse httpResponse = httpclient.execute(new HttpGet(params[0]));
            int statusCode = httpResponse.getStatusLine().getStatusCode();

            // 200 represents HTTP OK
            if (statusCode == 200) {
                String response = streamToString(httpResponse.getEntity().getContent());
                parseResult(response);
                result = 1; // Successful
            } else {
                result = 0; //"Failed
            }
        } catch (Exception e) {
            Log.d(TAG, e.getLocalizedMessage());
        }

        return result;
    }

    @Override
    protected void onPostExecute(Integer result) {
        // Download complete. Lets update UI

        if (result == 1) {
            mGridAdapter.setGridData(mGridData);
        } else {
            Toast.makeText(MainActivity.this, "network error", Toast.LENGTH_SHORT).show();
        }

        //Hide progressbar
        mProgressBar.setVisibility(View.GONE);
    }
}

String streamToString(InputStream stream) throws IOException {
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream));
    String line;
    String result = "";
    while ((line = bufferedReader.readLine()) != null) {
        result += line;
    }

    // Close stream
    if (null != stream) {
        stream.close();
    }
    return result;
}

/**
 * Parsing the feed results and get the list
 *
        * @param result
*/
private void parseResult(String result) {
    try {
        JSONObject response = new JSONObject(result);
        JSONArray posts = response.optJSONArray("posts");
        GridItem item;
        for (int i = 0; i < posts.length(); i++) {
            JSONObject post = posts.optJSONObject(i);
            item = new GridItem();
            JSONArray attachments = post.getJSONArray("attachments");
            if (null != attachments && attachments.length() > 0) {
                JSONObject attachment = attachments.getJSONObject(0);
                if (attachment != null)
                    item.setImage(attachment.getString("url"));
            }
            mGridData.add(item);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}}

2)GridItem.java

    public class GridItem {
    private String image;

    public GridItem() {
        super();
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

}

3)ImageAdapter.java

public class ImageAdapter extends ArrayAdapter<GridItem> {

private Context mContext;
private int layoutResourceId;
private ArrayList<GridItem> mGridData = new ArrayList<GridItem>();

public ImageAdapter(Context mContext, int layoutResourceId, ArrayList<GridItem> mGridData) {
    super(mContext, layoutResourceId, mGridData);
    this.layoutResourceId = layoutResourceId;
    this.mContext = mContext;
    this.mGridData = mGridData;
}

public void setGridData(ArrayList<GridItem> mGridData) {
    this.mGridData = mGridData;
    notifyDataSetChanged();
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    ViewHolder holder;

    if (row == null) {
        LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
        row = inflater.inflate(layoutResourceId, parent, false);
        holder = new ViewHolder();
        holder.imageView = (ImageView) row.findViewById(R.id.grid_item_image);
        row.setTag(holder);
    } else {
        holder = (ViewHolder) row.getTag();
    }

    GridItem item = mGridData.get(position);
    Picasso.with(mContext).load(item.getImage()).into(holder.imageView);
    return row;
}

static class ViewHolder {
    ImageView imageView;
}}

4)activity_main.xml中

<RelativeLayout 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"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">

<GridView
    android:id="@+id/grid_view"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    android:columnWidth="100dp"
    android:drawSelectorOnTop="true"
    android:gravity="center"
    android:numColumns="auto_fit"
    android:stretchMode="columnWidth"
    android:verticalSpacing="5dp"
    android:focusable="true"
    android:clickable="true"/>

<ProgressBar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/progressBar"
    android:layout_centerInParent="true"
    android:visibility="gone"/>

5)Grid_item.xml

<?xml version="1.0" encoding="utf-8"?>

<ImageView
android:layout_width="300dp"
android:layout_height="300dp"
android:id="@+id/grid_item_image"
android:scaleType="centerCrop" />

当我运行应用程序时,它崩溃并说“不幸的是应用已经停止” 我调试了代码,它在log cat

中显示了此错误消息
03-24 14:51:05.074    5099-5145/com.example.android.movieguide E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.example.android.movieguide, PID: 5099
java.lang.RuntimeException: An error occured while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:300)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
        at java.util.concurrent.FutureTask.run(FutureTask.java:242)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:841)
 Caused by: java.lang.NullPointerException: println needs a message
        at android.util.Log.println_native(Native Method)
        at android.util.Log.d(Log.java:158)
        at com.example.android.movieguide.MainActivity$AsyncHttpTask.doInBackground(MainActivity.java:91)
        at com.example.android.movieguide.MainActivity$AsyncHttpTask.doInBackground(MainActivity.java:71)
        at android.os.AsyncTask$2.call(AsyncTask.java:288)
        at java.util.concurrent.FutureTask.run(FutureTask.java:237)

在android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:587) 在java.lang.Thread.run(Thread.java:841)

2 个答案:

答案 0 :(得分:0)

试试这个

在gradle文件中添加图像加载程序库。

编译'com.github.bumptech.glide:glide:3.6.1'

<强> MainActivity.java

public class MainActivity extends AppCompatActivity {
private List<GridItem> gridItems;
private GridView gridView;
private ProgressBar progressBar;
private GridAdapter adapter;
protected Calendar calendar;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    calendar = Calendar.getInstance();
    init();
    getValue();
}

private void getValue() {
    progressBar.setVisibility(View.VISIBLE);
    HashMap<String, String> param = new HashMap<>();
    new NetworkRequest(MainActivity.this, new NetworkRequest.CallbackInterface() {
        @Override
        public void onRequestSuccess(JSONObject jsonObject) {
            progressBar.setVisibility(View.GONE);
            try {
                gridItems = new ArrayList<GridItem>();
                JSONArray result = jsonObject.getJSONArray("results");
                for (int i = 0; i < result.length(); i++) {
                    GridItem item = new GridItem();
                    item.setImageUrl(result.getJSONObject(i).getString("poster_path"));
                    gridItems.add(item);
                }
                adapter = new GridAdapter(getApplicationContext(), gridItems);
                gridView.setAdapter(adapter);

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

        @Override
        public void onRequestFailed(NetworkRequest.ErrorType errorType) {
            progressBar.setVisibility(View.GONE);
        }
    }, param, "GET").execute();
}


private void init() {
    gridView = (GridView) findViewById(R.id.grid);
    progressBar = (ProgressBar) findViewById(R.id.progress_bar);
}
}

<强> activity_main.aml

<RelativeLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">

<GridView
    android:id="@+id/grid"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true"
    android:columnWidth="100dp"
    android:drawSelectorOnTop="true"
    android:focusable="true"
    android:gravity="center"
    android:numColumns="auto_fit"
    android:stretchMode="columnWidth"
    android:verticalSpacing="5dp" />


<ProgressBar
    android:id="@+id/progress_bar"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:visibility="gone" />

</RelativeLayout>

<强> GridAdapter.java

public class GridAdapter extends ArrayAdapter<GridItem> {

private Context context;
private List<GridItem> gridItems;
private LayoutInflater inflater;

public GridAdapter(Context context, List<GridItem> contacts) {
    super(context, R.layout.grid_row, contacts);
    this.gridItems = contacts;
    this.context = context;
}


@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View view;
    ViewHolder viewHolder = new ViewHolder();
    if (convertView == null) {
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.grid_row, parent, false);
    } else {
        view = convertView;
    }
    viewHolder.imageView = (ImageView) view.findViewById(R.id.image);
    String url = gridItems.get(position).getImageUrl();
    if (url != null) {
        Glide.with(context).load(url).placeholder(R.drawable.dummy_icon).error(R.drawable.dummy_icon).into(viewHolder.imageView);
    }
    return view;
}

public class ViewHolder {
    ImageView imageView;
}
}

<强> grid_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFF"
android:padding="8dp"
android:orientation="horizontal">

<ImageView
    android:id="@+id/image"
    android:layout_width="150dp"
    android:layout_height="150dp" />

</LinearLayout>

<强> GridItem.java

public class GridItem {
private String imageUrl;

public String getImageUrl() {
    return imageUrl;
}

public void setImageUrl(String imageUrl) {
    this.imageUrl = imageUrl;
}
}

确保您的图片路径网址。

答案 1 :(得分:0)

我找到了答案,问题不在代码中,而是在电影数据库API中,要从服务器正确获取图像,您必须先将此网址“http://image.tmdb.org/t/p/w185/”添加到您的主网址中解析数据

    private void parseResult(String result) {
    try {
        JSONObject response = new JSONObject(result);
        JSONArray posters = response.optJSONArray("results");
        GridItem item;
        for (int i = 0; i < posters.length(); i++) {
            JSONObject poster = posters.optJSONObject(i);
            item = new GridItem();
            item.setImage("http://image.tmdb.org/t/p/w185/"+poster.getString("poster_path"));
            item.setOverview(poster.getString("overview"));
            item.setMovie_title(poster.getString("title"));
            item.setRelease_date(poster.getString("release_date"));
            item.setRating(poster.getString("vote_average"));
            mGridData.add(item);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}