草庐IT

android - 从 Activity 完成异步后在 Fragment 上填充 ListView

coder 2023-12-01 原文

我的主要 Activity 将从 url 异步获取 JSON 数据

这是MainActivity.java

public class MainActivity extends FragmentActivity implements ActionBar.TabListener{
    private ViewPager viewPager;
    private TabsPagerAdapter mAdapter;
    private ActionBar actionBar;

    //Tab titles
    private String[] tabs = {"Sermons", "More"};
    private String[] sermonsList = new String[0];

    //JSON URL for sermonList data
    private static String sermonListJSONUrl = "https://dl.dropboxusercontent.com/u/12345/index.php";

    //Variable to save JSON Object
    private static final String JSON_KEY_SERMONS = "sermon";

    private JSONObject sermonListJSONObject = null;
    private JSONArray sermonListJSONArray = null;
    SermonsFragment mSermonFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Call JSONParser Asynchronously to get sermonList in JSON Format

        new callJSONParserAsync().execute(sermonListJSONUrl);
        //this.mSermonFragment = (SermonsFragment) getFragmentManager().findFragmentById(android.R.id.list);
        this.mSermonFragment = (SermonsFragment) getFragmentManager().findFragmentById(R.id.pager);

        //Initialization
        viewPager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        mAdapter = new TabsPagerAdapter(getFragmentManager());

        viewPager.setAdapter(mAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        //Adding Tabs
        for(String tab_name : tabs) {
            actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
        }

        /**
         * on swiping the viewpager make respective tab selected
         */
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                //on changing the page
                //make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

这是activity_main.xml

<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

这是 SermonsFragment.java

public class SermonsFragment extends ListFragment {
    private String[] sermonsList;
    ArrayAdapter listAdapter;

    String imageUrl = "https://fbcdn-sphotos-b-a.akamaihd.net/" +
            "hphotos-ak-prn2/t1.0-9/10415605_10132423542_6220704573655530117_n.jpg";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        sermonsList = ((MainActivity)getActivity()).getSermonsList();

        //ListView for the sermon list, only show if there is something in listview
        listAdapter = new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1, sermonsList);

        if(listAdapter.getCount() != 0) {
            setListAdapter(listAdapter);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_sermons, container, false);

        // show The Image
        new getSermonBannerImage((ImageView) rootView.findViewById(R.id.series_banner))
                .execute(imageUrl);

        return rootView;
    }

    public void updateListView(String[] newData) {
        if(newData.length == 0) {
            Log.d("myTesting3", "sermonsList is Empty");
        } else {
            Log.d("myTestingSermonFragment", newData[0]);
            Log.d("myTestingSermonFragment", newData[1]);
        }

        sermonsList = newData;
        Log.d("myTestingSermonFragment", sermonsList[1]);
        this.listAdapter.clear();
        this.listAdapter.addAll(newData);
        this.listAdapter.notifyDataSetChanged();
    }

这是 fragment_sermon.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#222222" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <!-- Shows an image from your drawable resources -->
        <ImageView
            android:id="@+id/series_banner"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_gravity="center"
            android:src="@drawable/series_banner" />
        <!-- Closing tag for the horizontal nested layout -->

        <View
            android:layout_width="fill_parent"
            android:layout_height="10dp"
            android:layout_marginBottom="10dp"
            android:background="@android:color/darker_gray"/>

        <ListView
            android:id="@android:id/list"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="#ffffffff" />

        <TextView
            android:id="@android:id/empty"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="No Data" />
    </LinearLayout>
</RelativeLayout>

这是 TabsPagerAdapter.java

public class TabsPagerAdapter extends FragmentPagerAdapter {

    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int index) {
        switch (index) {
            case 0:
                //Sermons fragment activity
                return new SermonsFragment();
            case 1:
                //More fragment activity
                return new MoreFragment();

        }

        return null;
    }

    @Override
    public int getCount() {
        //get item count - equal to number of tabs
        return 2;
    }
}

最后是这个错误

07-27 16:42:27.921    1549-1555/org.myapp.myapp E/jdwp﹕ Failed writing handshake bytes: Broken pipe (-1 of 14)
07-27 16:42:29.941    1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ Getting MAX_TEXTURE_SIZE from GradienCache
07-27 16:42:29.941    1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ MAX_TEXTURE_SIZE: 16384
07-27 16:42:29.953    1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ Getting MAX_TEXTURE_SIZE from Caches::initConstraints()
07-27 16:42:29.953    1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ MAX_TEXTURE_SIZE: 16384
07-27 16:42:30.353    1549-1549/org.myapp.myapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: org.myapp.myapp, PID: 1549
    java.lang.NullPointerException
            at org.myapp.myapp.MainActivity$callJSONParserAsync.onPostExecute(MainActivity.java:174)
            at org.myapp.myapp.MainActivity$callJSONParserAsync.onPostExecute(MainActivity.java:157)
            at android.os.AsyncTask.finish(AsyncTask.java:632)
            at android.os.AsyncTask.access$600(AsyncTask.java:177)
            at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)

我不确定为什么会出现 OpenGLRenderer 错误,但自从我创建此应用程序以来它就一直存在并且它运行得很好,所以这不是问题(尽管如果你能指出如何解决这个问题伟大的)。 MainActivity.java:174 是 mSermonFragment.updateListView(sermonsList);

上的这一行

我怎样才能确保它被正确填充?最好是异步的,这样它就不会锁定 UI,也许可以在异步完成后稍后更新 ListView 。

最好,如果你也能指出,如何在异步期间做到这一点,它将检查是否有互联网连接, ListView 将显示加载圆圈,如果没有互联网,或空列表将不显示任何数据,否则将显示列表

最佳答案

因为你只有两个 fragment ,你可以跟踪它们保存实例。按照建议使用回调不是最佳选择。

因此,在您的寻呼机适配器中:

public class TabsPagerAdapter extends FragmentPagerAdapter {

    SermonsFragment mSermonsFragment;
    MoreFragment mMoreFragment;

    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
        this.mSermonsFragment = new SermonsFragment();
        this.mMoreFragment = new MoreFragment();
    }

    @Override
    public Fragment getItem(int index) {
        switch (index) {
            case 0:
                //Sermons fragment activity
                return mSermonsFragment;
            case 1:
                //More fragment activity
                return mMoreFragment;

        }

        return null;
    }

    @Override
    public int getCount() {
        //get item count - equal to number of tabs
        return 2;
    }

    public updateSermonsFragment(String[] data) {
         mSermonsFragment.updateData(data);
    }

    //i don't know what's the data type managed by MoreFragment
    public updateMoreFragment(Object data) {
         mMoreFragment.updateData(data)
    }
}

创建一个方法来更新 fragment 中的适配器:

public void updateData(String[] newData) {
    this.listAdapter.clear();
    for(int i = 0; i < newData.length; i++) {
        this.listAdapter.add(newData[i]);
    }
    this.listAdapter.notifyDataSetChanged();
}

然后您可以通过适配器方法从 AsyncTask 的 onPostExecute 调用此方法:

protected void onPostExecute(JSONObject jsonObject) {
    sermonListJSONObject = jsonObject;
    sermonListJSONArray = 
            parseJSONObjToJSONArray(sermonListJSONObject, JSON_KEY_SERMONS);

    String[] sermonsList;

    .... // here you need set an array with the strings you parsed

    //here you call the new method on the adapter to update your data.
    mAdapter.updateSermonsFragment(sermonsList);
 }

另一个最佳实践是在你的 fragment 中定义一个静态的 newInstace(String[] data) 方法,这样你就可以在第一次网络调用时初始化 fragment 数据,以确保你的 fragment 有一个要使用的数据集,然后如上所述进行更新。

关于android - 从 Activity 完成异步后在 Fragment 上填充 ListView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24873709/

有关android - 从 Activity 完成异步后在 Fragment 上填充 ListView的更多相关文章

  1. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  2. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  3. ruby - 匹配大写字母并用后续字母填充,直到一定的字符串长度 - 2

    我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种

  4. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  5. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  6. ruby - 如何用递增的值填充数组 Ruby - 2

    我正在尝试解决http://projecteuler.net/problem=1.我想创建一个方法,它接受一个整数,然后创建一个包含它前面的所有整数的数组,并将整数本身作为数组中的值。以下是我目前所拥有的。代码不起作用。defmake_array(num)numbers=Array.newnumcount=1numbers.eachdo|number|numbers 最佳答案 (1..num).to_a是您在Ruby中需要做的全部。1..num将创建一个Range对象,以1开始并以任意值num结束是。Range对象有to_a方法通过

  7. Ruby:行 "m = Hash.new {|h,k| h[k] = []}"完成了什么而 "Hash.new"没有完成? - 2

    一边学习thisRailscast我从Rack中看到了以下源代码:defself.middleware@middleware||=beginm=Hash.new{|h,k|h[k]=[]}m["deployment"].concat[[Rack::ContentLength],[Rack::Chunked],logging_middleware]m["development"].concatm["deployment"]+[[Rack::ShowExceptions],[Rack::Lint]]mendend我的问题是关于第三行。什么是传递block{|h,k|h[k]=[]}到Has

  8. ruby-on-rails - RoR中是否有任何内置方法可以为整数填充零? - 2

    如果我想要“00001”而不是“1”,除了我自己写填零方法之外,有没有内置的方法可以帮助我为整数填零? 最佳答案 puts"%05d"%1#00001参见:String::%,Kernel::sprintf这是正在发生的事情。%左侧的"%05d"是C风格的格式说明符。%右边的变量就是要格式化的东西。格式说明符可以像这样解码:%-格式说明符的开头0-用前导零填充5-长度为5个字符d-被格式化的是一个整数如果你要格式化多个东西,你会把它们放在一个数组中:"%d-%s"%[1,"One"]#=>1-one

  9. ruby-on-rails - 用一系列时间增量填充选择,加上其他选项 - 2

    使用RubyonRails,我使用给定的增量(例如每30分钟)用时间填充“选择”。目前我正在YAML文件中写出所有的可能性,但我觉得有一种更巧妙的方法。我想我想提供一个开始时间、一个结束时间、一个增量,并且目前只提供一个名为“关闭”的选项(想想“business_hours”)。所以,我的选择可能会显示:'Closed'5:00am5:30am6:00am...[allthewayto]...11:30pm谁能想出更好的方法,或者只是将它们全部“拼写”出来的最佳方法? 最佳答案 此答案基于@emh的答案。defcreate_hour

  10. ruby-on-rails - 自动完成搜索的 Rails 实现 - 2

    我不确定如何为我的搜索功能添加自动完成表单。"get"do%>nil%>我有一个具有自定义操作的Controllerdefquery@users=Search.user(params[:query])@article=Search.article(params[:query])end模型如下:defself.user(search)ifsearchUser.find(:all,:conditions=>['first_nameLIKE?',"%#{search}%"])elseUser.find(:all)endenddefself.article(search)ifsearchArt

随机推荐