目前,我正在开发一个应用程序,该应用程序在列表视图中显示基于JSON的API的内容。获取数据并使用适配器填充列表视图第一次正常工作。但是当我尝试使用Swipe刷新内容时,我第一次尝试刷新时遇到IllegalStateException错误:
W/System.err: java.lang.IllegalStateException: JsonReader is closed
W/System.err: at android.util.JsonReader.peek(JsonReader.java:361)
W/System.err: at android.util.JsonReader.expect(JsonReader.java:308)
W/System.err: at android.util.JsonReader.beginArray(JsonReader.java:277)
W/System.err: at com.cologne_international.cologneinternationalapp.notamActivity.readNotamArray(notamActivity.java:71)
W/System.err: at com.cologne_international.cologneinternationalapp.notamActivity.readJsonStream(notamActivity.java:63)
W/System.err: at com.cologne_international.cologneinternationalapp.notamActivity.updateNOTAMS(notamActivity.java:122)
W/System.err: at com.cologne_international.cologneinternationalapp.notamActivity$1.onRefresh(notamActivity.java:48)
W/System.err: at android.support.v4.widget.SwipeRefreshLayout$1.onAnimationEnd(SwipeRefreshLayout.java:187)
W/System.err: at android.support.v4.widget.CircleImageView.onAnimationEnd(CircleImageView.java:106)
W/System.err: at android.view.ViewGroup.finishAnimatingView(ViewGroup.java:6237)
W/System.err: at android.view.View.draw(View.java:17129)
W/System.err: at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
W/System.err: at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
W/System.err: at android.view.View.draw(View.java:17188)
W/System.err: at android.view.View.updateDisplayListIfDirty(View.java:16167)
W/System.err: at android.view.View.draw(View.java:16951)
W/System.err: at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
W/System.err: at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
W/System.err: at android.view.View.updateDisplayListIfDirty(View.java:16162)
W/System.err: at android.view.View.draw(View.java:16951)
W/System.err: at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
W/System.err: at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
W/System.err: at android.view.View.updateDisplayListIfDirty(View.java:16162)
W/System.err: at android.view.View.draw(View.java:16951)
W/System.err: at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
W/System.err: at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
W/System.err: at android.view.View.updateDisplayListIfDirty(View.java:16162)
W/System.err: at android.view.View.draw(View.java:16951)
W/System.err: at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
W/System.err: at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
W/System.err: at android.view.View.updateDisplayListIfDirty(View.java:16162)
W/System.err: at android.view.View.draw(View.java:16951)
W/System.err: at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
W/System.err: at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
W/System.err: at android.view.View.updateDisplayListIfDirty(View.java:16162)
W/System.err: at android.view.View.draw(View.java:16951)
W/System.err: at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
W/System.err: at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
W/System.err: at android.view.View.draw(View.java:17188)
W/System.err: at com.android.internal.policy.DecorView.draw(DecorView.java:753)
W/System.err: at android.view.View.updateDisplayListIfDirty(View.java:16167)
W/System.err: at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:648)
W/System.err: at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:654)
W/System.err: at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:762)
W/System.err: at android.view.ViewRootImpl.draw(ViewRootImpl.java:2800)
W/System.err: at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2608)
W/System.err: at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2215)
W/System.err: at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
W/System.err: at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6337)
W/System.err: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
W/System.err: at android.view.Choreographer.doCallbacks(Choreographer.java:686)
W/System.err: at android.view.Choreographer.doFrame(Choreographer.java:621)
W/System.err: at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
W/System.err: at android.os.Handler.handleCallback(Handler.java:751)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err: at android.os.Looper.loop(Looper.java:154)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6119)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
但是,当我尝试第二次重新加载时,一切都正常工作。
notamActivity Class:
public class notamActivity extends AppCompatActivity {
private static ListView lv;
private static AdapterNotam adbNotam;
private static SwipeRefreshLayout swipeContainer;
private static JsonReader reader;
private static Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notam);
context = getApplicationContext();
lv = (ListView) findViewById(R.id.list);
try {
adbNotam = new AdapterNotam(this, readJsonStream());
} catch (Exception e) {
e.printStackTrace();
}
lv.setAdapter(adbNotam);
swipeContainer = (SwipeRefreshLayout) findViewById(R.id.swiperefresh);
swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
Log.i("Called onRefresh", "onRefresh called from SwipeRefreshLayout");
notamActivity.updateNOTAMS();
}
});
}
public static List<Notam> readJsonStream() throws IOException {
try {
return readNotamArray(reader);
} finally {
reader.close();
}
}
public static List<Notam> readNotamArray(JsonReader reader) throws IOException {
List<Notam> notams = new ArrayList<Notam>();
reader.beginArray();
while (reader.hasNext()) {
notams.add(readNotam(reader));
}
reader.endArray();
return notams;
}
public static Notam readNotam(JsonReader reader) throws IOException {
int id = 0;
String datestart = null;
String dateend = null;
String text = null;
reader.beginObject();
while (reader.hasNext()) {
String jname = reader.nextName();
if (jname.equals("id")) {
id = Integer.parseInt(reader.nextString());
} else if (jname.equals("datestart")) {
datestart = reader.nextString();
} else if (jname.equals("dateend")) {
dateend = reader.nextString();
} else if (jname.equals("textde")) {
text = reader.nextString();
} else {
reader.skipValue();
}
}
reader.endObject();
return new Notam(id, text, datestart, dateend);
}
public static void setReader(JsonReader pReader){
reader = pReader;
}
public static Context getContext(){
return context;
}
public static void updateNOTAMS(){
new downloadNOTAMTask().execute("http://cologne-international.com/notam/json.php");
try {
adbNotam = new AdapterNotam(getContext(), readJsonStream());
} catch (Exception e) {
e.printStackTrace();
}
lv.setAdapter(adbNotam);
swipeContainer.setRefreshing(false);
}
}
downloadNOTAMTask Class:
class downloadNOTAMTask extends AsyncTask<String,Void,JsonReader>{
protected JsonReader doInBackground(String... url){
JsonReader reader = null;
try {
InputStream ls = new URL(url[0]).openStream();
reader = new JsonReader(new InputStreamReader(ls, "UTF-8"));
}catch(Exception e){
e.printStackTrace();
}
return reader;
}
protected void onPostExecute(JsonReader result){
notamActivity.setReader(result);
}
}
布局xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_event"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.cologne_international.cologneinternationalapp.eventActivity">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bt_back">
<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="match_parent"
/>
</android.support.v4.widget.SwipeRefreshLayout>
<Button
android:text="@string/button_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:id="@+id/bt_back"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:onClick="back"
style="@android:style/Widget.Holo.Button" />
</RelativeLayout>
答案 0 :(得分:0)
您在问题中发布的活动存在问题: -
但是,当我尝试第二次重新加载时,一切都正常工作。
这种情况正在发生,因为你没有以同步的方式做事。 (即你没有等待AsynTask完成)
下面我已经提到了编写更清晰,更不容易出错的代码的参考资料: -
notamActivity Class:
public class notamActivity extends AppCompatActivity {
private ListView lv;
private AdapterNotam adbNotam;
private SwipeRefreshLayout swipeContainer;
private Context context;
private DownloadNOTAMTask downloadNOTAMTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notam);
context = getApplicationContext();
lv = (ListView) findViewById(R.id.list);
//to initially get the list of Notams
updateNOTAMS();
swipeContainer = (SwipeRefreshLayout) findViewById(R.id.swiperefresh);
swipeContainer.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
Log.i("Called onRefresh", "onRefresh called from SwipeRefreshLayout");
updateNOTAMS();
}
});
}
public void cancelTask(DownloadNOTAMTask downloadNOTAMTask) {
if (downloadNOTAMTask != null && downloadNOTAMTask.getStatus() == AsyncTask.Status.RUNNING)
downloadNOTAMTask.cancel(true);
}
//you should create a reference to cancel the task when the activity is closing
public void updateNOTAMS() {
cancelTask(downloadNOTAMTask);
downloadNOTAMTask = new DownloadNOTAMTask(new GenericCallBack() {
@Override
public void success(List<Notam> notamList) {
//you don't need to setup adapter again and again
//just use setDataSetChanged
adbNotam = new AdapterNotam(notamActivity.this, notamList);
lv.setAdapter(adbNotam);
swipeContainer.setRefreshing(false);
}
@Override
public void failure() {
swipeContainer.setRefreshing(false);
}
}).execute("http://cologne-international.com/notam/json.php");
}
//interface help you to get callback from the downloadNOTAMTask
interface GenericCallBack {
void success(List<Notam> notamList);
void failure();
}
}
DownloadNOTAMTask Class:
public class DownloadNOTAMTask extends AsyncTask<String, Void, List<Notam>> {
private final notamActivity.GenericCallBack callBack;
public DownloadNOTAMTask(notamActivity.GenericCallBack genericInterface) {
this.callBack = genericInterface;
}
protected List<Notam> doInBackground(String... url) {
JsonReader reader = null;
List<Notam> notamList = null;
try {
InputStream ls = new URL(url[0]).openStream();
reader = new JsonReader(new InputStreamReader(ls, "UTF-8"));
notamList = readNotamArray(reader);
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return notamList;
}
@Override
protected void onPostExecute(List<Notam> notams) {
if (callBack != null) {
if (notams != null)
callBack.success(notams);
else
callBack.failure();
}
}
private List<Notam> readNotamArray(JsonReader reader) throws IOException {
List<Notam> notams = new ArrayList<>();
reader.beginArray();
while (reader.hasNext()) {
notams.add(readNotam(reader));
}
reader.endArray();
return notams;
}
private Notam readNotam(JsonReader reader) throws IOException {
int id = 0;
String datestart = null;
String dateend = null;
String text = null;
reader.beginObject();
while (reader.hasNext()) {
String jname = reader.nextName();
switch (jname) {
case "id":
id = Integer.parseInt(reader.nextString());
break;
case "datestart":
datestart = reader.nextString();
break;
case "dateend":
dateend = reader.nextString();
break;
case "textde":
text = reader.nextString();
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
return new Notam(id, text, datestart, dateend);
}
}
布局xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_event"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.cologne_international.cologneinternationalapp.eventActivity">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/swiperefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bt_back">
<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="match_parent"
/>
</android.support.v4.widget.SwipeRefreshLayout>
<Button
android:text="@string/button_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:id="@+id/bt_back"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:onClick="back"
style="@android:style/Widget.Holo.Button" />
</RelativeLayout>