使用extras作为构造函数的参数检索JSON数据

时间:2016-03-13 17:49:40

标签: android json

大家好,我正在尝试以JSON格式检索一些电影信息,但我似乎无法弄清楚我的代码是什么问题。数据检索和处理本身都有效,但问题是,当我在EditText中传递我的标题输入并从另一个活动中检索该数据时,我似乎无法使用它。我将检索到的额外内容传递给我的数据处理类ParseJsonData的参数。但是,我在设置title.setText(parseJsonData.getMovie().getTitle())的位置得到一个空指针异常。这个奇怪的方面是,如果我只是通过自己传递标题在MainActivity中运行ParseJsonData,我就能够检索通过日志观察到的数据标题。当我传递额外的构造函数参数时,我应该注意什么?

public class ResultsPage extends AppCompatActivity {

private final String LOG_TAG = getClass().getSimpleName();
private TextView title;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_results_page);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    setTextViews();

}

private void setTextViews () {
    Bundle bundle = getIntent().getExtras();

    String movieTitle = bundle.getString("title");

    Log.v(LOG_TAG, "title recieved is : " + movieTitle);

    ParseJsonData parseJsonData = new ParseJsonData(movieTitle);
    parseJsonData.execute();

    title.setText(parseJsonData.getMovie().getTitle());

}

}

下面是ParseJsonData

public class ParseJsonData extends GetRawData{

private String mUrl;
private String title;
private static final String LOG_TAG = "ParseJsonData";
private Movie movie;

public ParseJsonData(String title) {
    this.title = title;
    processUrl();
}

@Override
public void execute() {
    super.setUrl(mUrl);
    ParseJsonDataBackground parseJsonDataBackground = new ParseJsonDataBackground();
    parseJsonDataBackground.execute(mUrl);
}

public Movie getMovie() {
    return movie;
}

private void processUrl () {

    final String BASE_URL = "http://www.omdbapi.com/";
    final String MOVIE_TITLE = "t";
    final String MOVIE_YEAR = "y";
    final String MOVIE_PLOT = "plot";
    final String MOVIE_DATA_TYPE = "r";

    mUrl = Uri.parse(BASE_URL).buildUpon().appendQueryParameter(MOVIE_TITLE, title).appendQueryParameter(MOVIE_YEAR, "").appendQueryParameter(MOVIE_PLOT, "short").appendQueryParameter(MOVIE_DATA_TYPE, "json").build().toString();
    Log.v(LOG_TAG, "New Url address is : " + mUrl);
}

public class ParseJsonDataBackground extends GetRawDataBackground {
    @Override
    protected String doInBackground(String... params) {
        return super.doInBackground(params);
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        processData(getmData());
    }

    private void processData (String mData){
        try {
            final String MOVIE_TITLE = "Title";

            JSONObject jsonObject = new JSONObject(mData);

            Log.v(LOG_TAG, mData);

            String title = jsonObject.getString(MOVIE_TITLE);

            movie = new Movie(title);
            Log.v(LOG_TAG, "Title of the movie is " + movie.getTitle());
        }catch (JSONException e){
            Log.e(LOG_TAG, "Error retrieving JsonData");
            e.printStackTrace();
        }
    }
}
}

这是GetRawData的扩展,它位于

之下
public class GetRawData {

private String url;
private String mData;
private static final String LOG_TAG = "GetRawData";

public GetRawData() {
}

public String getmData() {
    return mData;
}

public void setUrl(String url) {
    this.url = url;
}

public void execute () {
    GetRawDataBackground getRawDataBackground = new GetRawDataBackground();
    getRawDataBackground.execute(url);
}

public class GetRawDataBackground extends AsyncTask<String, Void, String>{

    private StringBuffer stringBuffer;

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

        mData = processDownloads (params[0]);

        if (mData == null){
            Log.e(LOG_TAG, "Null returned during processing");
            return null;
        }

        return mData;
    }

    @Override
    protected void onPostExecute(String s) {
        Log.v(LOG_TAG, "Data retrieved is : " + s);
        super.onPostExecute(s);
    }

    private String processDownloads (String mUrl){

        HttpURLConnection connection = null;
        BufferedReader reader = null;

        try {
            if (mUrl == null){
                return null;
            }
            URL url = new URL(mUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            int responseCode = connection.getResponseCode();
            Log.d(LOG_TAG, "Response code is : " + responseCode);

            reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            stringBuffer = new StringBuffer();

            String line = new String();

            while ((line = reader.readLine()) != null) {
                stringBuffer.append(line);
            }

            return stringBuffer.toString();


        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "MalformedURLException");
            return null;
        } catch (IOException e){
            Log.e(LOG_TAG, "IOException in making connection");
            return null;
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    Log.e(LOG_TAG, "Error attempting to close reader");
                }
            }
        }


    }
}
}

1 个答案:

答案 0 :(得分:1)

这是因为你在后台任务中实例化电影。它发生在并行线程(线程2)中。你的主线程调用getMovite()。getTitle();但由于线程2仍在运行,因此尚未设置电影。

您应该从MainActivity传递回调到ParseJsonData并在onPostExecute中调用回调。确保在更新文本视图时返回MainThread。

public class ParseJsonDataBackground extends GetRawDataBackground {
    public interface ParseJsonCallback{
        void onJsonReady(Movie movie);
    }
    private ParseJsonCallback callback;

    ParseJsonDataBackground(ParseJsonCallback callback){
        this.callback = callback;
    }

    .....
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        processData(getmData());
        callback.onJsonReady(movie);
    }
    .....
}

在MainActivity中

....
ParseJsonData parseJsonData = new ParseJsonData(movieTitle, new ParseJsonCallback(){
    void onJsonReady(Movie movie){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                  title.setText(movie.getTitle());
            }
        });  
    }

});
parseJsonData.execute();
....