2012年10月26日 星期五

[Android] XMLとAsyncTaskと動けないnotifyDataSetChanged

Android開発し始まった。Objective-Cに慣れたわたしには、ちょっと難しい、Javaは多分10年も触らなかった。

一日中どうやってXMLファイルを読み込み、ListViewに表示するかにチャレンジしてた。

とにかく書いておこう。








問題一:ネットでXMLファイルをロードしようとしたが、android.os.NetworkOnMainThreadExceptionというエラーが出てしまった。




解決方法はいろいろありそう:一つはStrictMode.ThreadPolicyでの設定すること、でも調べてみた結果、あまりいいアイデアではなさそうだ。

代わりにAsyncTaskを使う。そうしたらXMLを解析する作業は全部AsyncTaskに済む。



問題二:ListViewをnotifyDataSetChangedで更新しようとしたが、エラーが出てしまう。
結局、Runnableを使いました。なんとなく動けた。

最後のコードはこの感じ、XMLファイルはAsyncTaskで読み込んで、終わったらRunnableでListViewを更新する:


public class App extends Activity {

private ArrayList<String> items;

private ListView klist;

private ArrayAdapter<String> adapter;




public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.appLayout);
klist=(ListView)findViewById(R.id.klist);
items = new ArrayList<String>();

adapter = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, items);

klist.setAdapter(adapter);







  try {
    DownloadFileAsync d = new DownloadFileAsync();
    d.execute("http://....");
  } catch (Exception e) {
    System.out.println("XML Pasing Excpetion = " + e);
  }
}

void refreshListView() {
  adapter.notifyDataSetChanged();
  klist.invalidateViews();
}


class DownloadFileAsync extends AsyncTask<String, String, String> {
Document doc;

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

@Override
protected String doInBackground(String... aurl) {
try {
URL url = new URL(aurl[0]);

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc= db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();


NodeList nodeList = doc.getElementsByTagName("bookdata");

   
name = new String[nodeList.getLength()];
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);

Element fstElmnt = (Element) node;
NodeList nameList = fstElmnt.getElementsByTagName("title");

Element nameElement = (Element) nameList.item(0);
nameList = nameElement.getChildNodes();
items.add(((Node) nameList.item(0)).getNodeValue());
}



Runnable run = new Runnable(){
  public void run(){
    refreshListView();
  }
};
runOnUiThread(run);

} catch (Exception e) {
  System.out.println("Excpetion = " + e);
}

return null;
}

protected void onProgressUpdate(String... progress) {   }

@Override
protected void onPostExecute(String unused) {}
} //end class 
DownloadFileAsync

}


雑々ですみません。