android怎么刷新适配器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android怎么刷新适配器相关的知识,希望对你有一定的参考价值。

参考技术A totalList = list; adapter.notifyDataSetChanged(); totalList.addAll(list); adapter.notifyDataSetChanged(); //这就是刷新适配器的方法 参考技术B 用对象点这个notifyDataSetChanged(); 方法就可以刷新适配器了
Adapter.notifyDataSetChanged();
就像这样,帮助到你请采纳。。。。

尝试刷新内容时,Android JsonReader 已关闭

【中文标题】尝试刷新内容时,Android JsonReader 已关闭【英文标题】:Android JsonReader is closed when attempting to refresh content 【发布时间】:2017-01-02 19:23:37 【问题描述】:

目前,我正在开发一个在列表视图中显示基于 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 类:

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

下载NOTAMTask 类:

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_
    android:layout_
    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_
        android:layout_
        android:layout_above="@+id/bt_back">

        <ListView
        android:id="@+id/list"
        android:layout_
        android:layout_
         />

    </android.support.v4.widget.SwipeRefreshLayout>

    <Button
        android:text="@string/button_back"
        android:layout_
        android:layout_
        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>

【问题讨论】:

你做错了。首先,请不要对您正在处理的所有对象进行静态引用,这可能会导致大量内存泄漏,其次,如果您正在执行 asncTask,您应该等待结果然后进行处理。 【参考方案1】:

您在问题中发布的活动存在问题:-

您不应持有对上下文或任何视图的静态引用,这可能会导致内存泄漏 当您使用 AsynTask 时,请尝试传递一个接口以恢复通信,就像我在以下活动中所做的那样。 在后台执行 JSON 解析,因为它可能会以繁重的处理结束并显示 ANR。

但是,当我再次尝试重新加载时,一切正常。

这是因为您没有以同步方式做事。 (即,您不是在等待 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();
    

下载NOTAMTask 类:

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_
    android:layout_
    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_
        android:layout_
        android:layout_above="@+id/bt_back">

        <ListView
        android:id="@+id/list"
        android:layout_
        android:layout_
         />

    </android.support.v4.widget.SwipeRefreshLayout>

    <Button
        android:text="@string/button_back"
        android:layout_
        android:layout_
        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>

【讨论】:

以上是关于android怎么刷新适配器的主要内容,如果未能解决你的问题,请参考以下文章

Android Q 基站刷新接口源码分析 & 适配双卡手机基站刷新逻辑

Android Q 基站刷新接口源码分析 & 适配双卡手机基站刷新逻辑

Android Q 基站刷新接口源码分析 & 适配双卡手机基站刷新逻辑

Android Q 基站刷新接口源码分析 & 适配双卡手机基站刷新逻辑

Android Q 基站刷新接口源码分析 & 适配双卡手机基站刷新逻辑

RecyclerView(自定义适配器)不刷新搜索列表