Asynctask 및 타이머를 사용하여 XML을 얻는 방법은 무엇입니까?
-
19-09-2019 - |
문제
서버에서 XML 데이터를 반복적으로 가져 오려면 Asynctask와 타이머를 사용하려고합니다. 마크 머피의 제안.
다음 오류가 발생합니다.
01-07 16:11:26.705: ERROR/AndroidRuntime(729):
Caused by: java.lang.RuntimeException:
Can't create handler inside thread that has not
called Looper.prepare()
Windows에서 Eclipse와 함께 SDK 1.5를 사용하고 있습니다.
문서, StackoverFlow 및 Android Developers Group에서 문서를 살펴 보았지만 오류의 원인이나 수정 방법이 무엇인지 명확하지 않습니다.
즉, 비동기와 타이머없이 데이터를 한 번 가져 와서 문제없이 SAX를 통해 구문 분석 할 수 있습니다.
아래의 전체 앱 코드.
순진한 오류를 실례합니다. 저는 Android를 처음 사용합니다.
package com.foo.bar.myactivity;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Timer timer;
timer = new Timer();
timer.schedule(new MyTimerTask(), 0, 1000);
}
public class MyAsyncTask extends AsyncTask<String, Integer, MyData> {
protected MyData doInBackground(String... string) {
MyData myData = new MyData();
try {
URL url = new URL("http://www.example.com/my.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
MyHandler myHandler = new MyHandler();
xr.setContentHandler(myHandler);
System.setProperty("http.proxyHost", "www-cache.example.com");
System.setProperty("http.proxyPort", "80");
xr.parse(new InputSource(url.openStream()));
myData = myHandler.getParsedData();
return myData;
} catch (Exception e) {
Log.e(">>>>>>>>>>>> Error getting myData: ", e.getMessage(), e);
return myData;
}
}
protected void onProgressUpdate(Integer... progress) {
// setProgressPercent(progress[0]);
}
protected void onPostExecute(MyData myData) {
Log.d(">>>>>>>>>>>>>My data: ", myData.toString());
}
}
public class MyTimerTask extends TimerTask {
public void run() {
try {
new MyAsyncTask().execute("");
} catch (Exception e) {
Log.e(">>>>>>>>>>>> Error executing MyAsyncTask: ", e.getMessage(), e);
}
}
}
}
해결책
문제는 Timertask를 사용하는 것입니다. Timertask Run은 다음과 같은 핸들러에 게시해야합니다.
private Handler mHandler = new Handler();
public class MyTimerTask extends TimerTask {
public void run() {
mHandler.post(
new Runnable() {
public void run() {
new MyAsyncTask().execute("");
}
};
)
}
}
물론 이것은 조금 추악 해지고 있으므로 익명의 수업을 꺼내는 것이 좋습니다.
다른 팁
제임스의 대답 덕분에 이것을 일하게했습니다.
누구에게나 유용한 경우 아래 코드를 포함 시켰습니다.
경고 개발자! 코드는 나에게 효과가 있지만 오류가 포함될 수 있습니다.
package com.example.test;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
public class MyXmlPoller extends Activity {
private Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new Timer().schedule(new MyTimerTask(), 0, 1000);
}
private class MyAsyncTask extends AsyncTask<Integer, Integer, MyData> {
protected MyData doInBackground(Integer... counter) {
MyData myData = new MyData();
try {
URL url = new URL("http://www.example.com/my.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
MySAXHandler mySAXHandler = new Handler();
xr.setContentHandler(mySAXHandler);
xr.parse(new InputSource(url.openStream()));
myData = mySAXHandler.getParsedData();
return myData;
} catch (Exception e) {
Log.e("!!!!!!!!!! MyAsyncTask doInBackground error", e.getMessage(), e);
return myData;
}
}
protected void onPostExecute(MyData myData) {
Log.d("+++++++++++++ MyAsyncTask onPostExecute", myData.toString());
}
} // MyAsyncTask
public class MyTimerTask extends TimerTask {
private Runnable runnable = new Runnable() {
public void run() {
new MyAsyncTask().execute();
}
};
public void run() {
handler.post(runnable);
}
}
}
문제는 당신이 전화하지 않은 것 같습니다 Looper.prepare()
. 당신은 그것을 볼 수 있습니다 문서화 Looper
.
ㅏ Handler
메시지를 처리하려면 메시지 루프가 필요하고 기본적으로 스레드에는 스레드가 없습니다.
그것은 것 같습니다 AsyncTask
a Handler
내부적 그래서 추가하십시오 Looper.prepare()
당신의 꼭대기에 run()
방법 MyTimerTask
그리고 그것은 당신의 문제를 해결해야합니다.
Alarm Manager와 함께 서비스를 사용합니다
I Intent updateIntent = new Intent(ACTION_UPDATE_ALL);
updateIntent.setClass(this, UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, updateIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, nextUpdate, pendingIntent);
문제는 doinbackground ()가 실행되는 스레드에서 핸들러 객체를 만들 수 없다는 것입니다. onpreexecute () 메소드를 구현하고 설정 코드를 넣습니다. 이 라인을 OnPreeXecute () 메소드로 옮기십시오.
URL url = new URL("http://www.example.com/my.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
MyHandler myHandler = new MyHandler();
xr.setContentHandler(myHandler);