2017-01-02 11 views
0

В настоящее время я работаю над приложением, которое отображает содержимое API на основе JSON в списке. Приобретение данных и использование адаптера для заполнения списка отображаются в первый раз. Но когда я пытаюсь обновить содержимое с помощью Размах, чтобы обновить, первый раз, когда я пытаюсь обновить я получаю ошибку IllegalStateException:Android JsonReader закрыт при попытке обновить контент

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 Класс:

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 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); 
    } 
} 

Layout 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

Вы делаете все это неправильно. Во-первых, пожалуйста, не держите статические ссылки на весь объект, над которым вы работаете, может закончиться много утечки памяти, а во-вторых, если вы делаете asncTask, вы должны дождаться результата, а затем выполните обработку. –

ответ

0

Существует проблема с деятельностью, которые вы опубликовали в вопросе: -

  • Вы не должны хранить статическую ссылку на контекст или любое представление, это может закончиться утечкой памяти.
  • Когда вы используете AsynTask, попробуйте передать интерфейс, чтобы вернуть связь, как я сделал в нижеуказанной операции.
  • Разбирайте JSON в фоновом режиме, так как это может закончиться тяжелой обработкой и показать вам ANR.

However, when I try to reload for a second time, everything is working as it should.

Это происходит потому, что вы не делаете вещи в синхронном режиме. (Т. Е Вы не ждут AsynTask, чтобы получить законченный)

Ниже я дал вам ссылку писать более чистый и менее подвержен ошибкам код: -


notamActivity Класс:

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 Класс:

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>