大家好,我正在尝试以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");
}
}
}
}
}
}
答案 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();
....