AsyncTask를 사용하여 URL을 열고, 서버에 액세스하고, 콘텐츠를 가져 와서 기본 활동의 목록보기에 표시합니다. 추출 된 컨텐츠는 신문의 제목과 웹 사이트에 대한 URL로 구성되며, "읽음"버튼을 클릭하면 두 번째 활동에서 WebView에 표시됩니다. 프로그램을 곧바로 작성했는데 작동하지만 되돌아 보았을 때 부적절한 부분을 발견 했으므로 주로 코드가 어떻게 작동하는지 분명히 밝히고 싶습니다. 여기에 주요 활동에 대한 코드입니다 :android AsyncTask 및 UI 스레드 상호 작용
package com.example.newsapp;
public class MainActivity extends Activity {
static final private String LOG_TAG = "main";
private ArrayList<Content> aList;
private class Content{
Content() {};
public String title;
public String url;
}
private class MyAdapter extends ArrayAdapter<Content>{
int resource;
public MyAdapter(Context _context, int _resource, List<Content> titles) {
super(_context, _resource, titles);
resource = _resource;
// this.context = _context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout newView;
final Content content = getItem(position);
// Inflate a new view if necessary.
if (convertView == null) {
newView = new LinearLayout(getContext());
String inflater = Context.LAYOUT_INFLATER_SERVICE;
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(inflater);
vi.inflate(resource, newView, true);
} else {
newView = (LinearLayout) convertView;
}
// Fills in the view.
TextView tv = (TextView) newView.findViewById(R.id.listText);
ImageButton b = (ImageButton) newView.findViewById(R.id.listButton);
b.setBackgroundResource(0);
tv.setText(content.title);
Typeface type = Typeface.createFromAsset(getAssets(),"LiberationSerif-BoldItalic.ttf");
tv.setTypeface(type);
// Sets a listener for the button, and a tag for the button as well.
b.setTag(Integer.toString(position));
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Reacts to a button press.
Intent intent = new Intent(MainActivity.this, WebPage.class);
Bundle bundle = new Bundle();
bundle.putString("URL", content.url);
intent.putExtras(bundle);
startActivity(intent);
}
});
return newView;
}
}
class MyAsyncTask extends AsyncTask<String, String, String> {
private ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
InputStream inputStream = null;
String result = "";
Content content;
protected void onPreExecute() {
super.onPreExecute();
progressDialog.setMessage("Downloading the news...");
progressDialog.show();
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface arg0) {
MyAsyncTask.this.cancel(true);
}
});
}
@Override
protected String doInBackground(String... params) {
String url_select = params[0];
ArrayList<NameValuePair> param = new ArrayList<NameValuePair>();
try {
// Set up HTTP post
// HttpClient is more then less deprecated. Need to change to URLConnection
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url_select);
httpPost.setEntity(new UrlEncodedFormEntity(param));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
// Read content & Log
inputStream = httpEntity.getContent();
} catch (UnsupportedEncodingException e1) {
Log.e("UnsupportedEncodingException", e1.toString());
e1.printStackTrace();
} catch (ClientProtocolException e2) {
Log.e("ClientProtocolException", e2.toString());
e2.printStackTrace();
} catch (IllegalStateException e3) {
Log.e("IllegalStateException", e3.toString());
e3.printStackTrace();
} catch (IOException e4) {
Log.e("IOException", e4.toString());
e4.printStackTrace();
}
// Convert response to string using String Builder
try {
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "iso-8859-1"), 8);
StringBuilder sBuilder = new StringBuilder();
String line = null;
while ((line = bReader.readLine()) != null) {
sBuilder.append(line + "\n");
}
inputStream.close();
result = sBuilder.toString();
} catch (Exception e) {
Log.e("StringBuilding & BufferedReader", "Error converting result " + e.toString());
}
return result;
} // protected Void doInBackground(String... params)
protected void onPostExecute(String result) {
//parse JSON data
try {
super.onPostExecute(result);
Log.i(LOG_TAG, result);
JSONObject object = new JSONObject(result);
JSONArray jArray = object.getJSONArray("sites");
for(int i=0; i < jArray.length(); i++) {
JSONObject jObject = jArray.getJSONObject(i);
content = new Content();
if (jObject.has("title") && jObject.has("url")){
content.title = jObject.getString("title");
content.url = jObject.getString("url");
aList.add(content);
aa.notifyDataSetChanged();
}
} // End Loop
progressDialog.dismiss();
} catch (JSONException e) {
// progressDialog.dismiss();
Log.e("JSONException", "Error: " + e.toString());
}
} // protected void onPostExecute(String result)
}
private MyAdapter aa;
private MyAsyncTask loadTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadTask = new MyAsyncTask();
loadTask.execute("http://luca-ucsc.appspot.com/jsonnews/default/news_sources.json");
aList = new ArrayList<Content>();
aa = new MyAdapter(this, R.layout.list_element, aList);
ListView myListView = (ListView) findViewById(R.id.listView1);
myListView.setAdapter(aa);
aa.notifyDataSetChanged();
}
public void refresh(View v){
if (loadTask.getStatus() == AsyncTask.Status.FINISHED){
aList.clear();
aa.notifyDataSetChanged();
new MyAsyncTask().execute("http://luca-ucsc.appspot.com/jsonnews/default/news_sources.json");
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
그래서 당신이 onCreate()
만 후 loadTask.execute()
, 나는 alist와 AA의 객체를 생성 할 것을 알 수 있습니다,하지만 난 이미 AsyncTaks 클래스에 onPostExecute()
에서 그들을 사용하고 있습니다 따라서 onPostExecute()
과 UI가 동일한 스레드에 있으므로 onPostExecute()
의 코드가 먼저 실행되어야하므로 여기에서 어떤 일이 발생하는지 명확하지 않습니다.
onPostExecute()
에 내가
aList = new ArrayList<Content>();
aa = new MyAdapter(this, R.layout.list_element, aList);
을 넣어해야한다고 생각. 또한 방법이기 때문에 aa.notifyDataSetChanged();
을 onPostExecute()
에서 삭제해도 문제가되지 않지만 실제로는 목록보기가 내용없이 비어있게됩니다. 사실 loadTask.execute()
뒤에있는 코드를 onPostExecute()
메서드의 if 블록에 넣으면 문제가 발생하거나 응용 프로그램이 중단됩니다. 누군가 통찰력이나 힌트를 줄 수 있다면 좋을 것입니다. 읽어 주셔서 감사합니다.
하지만 onPostExecute() 메소드에서 UI를 업데이트해야합니다. – Piyush
@PiYusHGuPtA 나는 생각한다.notifyDataSetChanged()는 UI를 업데이트합니다. –