草庐IT

java - 由于异步 Firebase 调用,主线程做了太多工作?

coder 2023-11-22 原文

我的应用程序不断收到错误消息,提示 I/Choreographer:跳过 252 帧!应用程序可能在其主线程上做了太多工作。 我认为这会导致我的 UI 出现一些延迟,这是我不希望的。我认为这是因为当我执行 Firebase 查询时,当我执行 onDataChange() 时,它似乎总是在主 UI 线程中执行。我有大约 5 个类似于下面的 Firebase 查询。因此,我尝试将我的代码从 onDataChange() 方法移动到 AsyncTask 并在 onPostExecute() 方法上更新 UI 线程异步任务。但是,当我尝试这样做时,onPostExecute() 方法永远不会完成。这是我的尝试:

public void getPublicPosts(final View progressOverlay, final View fragmentView, final Context context) {
    //Need to do order by / equal to.
    Firebase postsRef = firebaseRef.child("Posts");
    Query query = postsRef.orderByChild("privacy").equalTo("Public");
    query.keepSynced(true);
    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (final DataSnapshot postSnapShot : dataSnapshot.getChildren()) {
                AsyncTask task = new AsyncTask<URL, Integer, Long>() {
                    @Override
                    protected Long doInBackground(URL... params) {
                        Post post = postSnapShot.getValue(Post.class);
                        List<Post> publicPosts = application.getPublicAdapter().getPosts();
                        if (post.getPrivacy().equals("Public") && application.getPublicAdapter().containsId(publicPosts, post.getId()) == null) {
                            application.getPublicAdapter().getPosts().add(0, post);
                        }
                        return null;
                    }
                    @Override
                    protected void onProgressUpdate(Integer... progress) {
                    }

                    @Override
                    protected void onPostExecute(Long result) {
                        System.out.println("Finished executing public");
                        populateNewsFeedList(fragmentView, application.getPublicAdapter(), TabEnum.Public, context);
                        if (progressOverlay.getVisibility() == View.VISIBLE) {
                            System.out.println("getPublicPosts: DONE");
                            AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200);
                            fragmentView.findViewById(R.id.rv_public_feed).setVisibility(View.VISIBLE);
                        }
                    }
                };
                `task.execute();`
            }
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
        }
    });
}

任何对此的帮助都会有所帮助。如果有人可以帮助我,那就太好了。谢谢!

编辑:添加函数来创建AsyncTask

public AsyncTask asyncTaskWrapper(final DataSnapshot dataSnapshot, final View progressOverlay, final View fragmentView, final Context context) {
        AsyncTask task = new AsyncTask<URL, Integer, Long>() {
            @Override
            protected Long doInBackground(URL... params) {
                for (final DataSnapshot postSnapShot : dataSnapshot.getChildren()) {
                    Post post = postSnapShot.getValue(Post.class);
                    List<Post> publicPosts = application.getPublicAdapter().getPosts();
                    if (post.getPrivacy() == PrivacyEnum.Public && application.getPublicAdapter().containsId(publicPosts, post.getId()) == null) {
                        application.getPublicAdapter().getPosts().add(0, post);
                    }
                }
                return null;
            }
            @Override
            protected void onProgressUpdate(Integer... progress) {
            }

            @Override
            protected void onPostExecute(Long result) {
                System.out.println("Finished executing public");
                TabsUtil.populateNewsFeedList(fragmentView, application.getPublicAdapter(), TabEnum.Public, context);
                if (progressOverlay.getVisibility() == View.VISIBLE) {
                    System.out.println("getPublicPosts: GONE");
                    AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200);
                    fragmentView.findViewById(R.id.rv_public_feed).setVisibility(View.VISIBLE);
                }
            }
        };
        return task;
    }

公共(public)帖子功能:

public void getPublicPosts(final View progressOverlay, final View fragmentView, final Context context) {
    //Need to do order by / equal to.
    Firebase postsRef = firebaseRef.child("Posts");
    Query query = postsRef.orderByChild("privacy").equalTo(PrivacyEnum.Public.toString());
    query.keepSynced(true);
    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            asyncTaskWrapper(dataSnapshot, progressOverlay, fragmentView, context);
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            TabsUtil.populateNewsFeedList(fragmentView, application.getPublicAdapter(), TabEnum.Public, context);
        }
    });
}

最佳答案

您的主线程可能很慢,因为您正在运行一个包含许多对象的循环。但是,不知道您到底在执行什么,这只是一个猜测。

但我对您的 AsyncTask 有疑问,我认为它永远无法与您发布的代码一起使用。

AsyncTask 需要一个 URL 数组。你没有通过任何。如果不需要 URL 作为输入,则只需使用:

AsyncTask task = new AsyncTask<Void, Boolean, Boolean>() 

你试试如何排除故障:

    AsyncTask task = new AsyncTask<URL, Boolean, Boolean>() {
        @Override
        protected Boolean doInBackground(URL... params) {
            for (final DataSnapshot postSnapShot : dataSnapshot.getChildren()) {
                Post post = postSnapShot.getValue(Post.class);
                List<Post> publicPosts = application.getPublicAdapter().getPosts();
                if (post.getPrivacy() == PrivacyEnum.Public && application.getPublicAdapter().containsId(publicPosts, post.getId()) == null) {
                    application.getPublicAdapter().getPosts().add(0, post);
                }
            }
            return true;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            if(result){
                System.out.println("Finished executing public");
                TabsUtil.populateNewsFeedList(fragmentView, application.getPublicAdapter(), TabEnum.Public, context);
                if (progressOverlay.getVisibility() == View.VISIBLE) {
                    System.out.println("getPublicPosts: GONE");
                    AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200);
                    fragmentView.findViewById(R.id.rv_public_feed).setVisibility(View.VISIBLE);
                }
            }
        }
    };

然后通过触发来执行任务:

URL[] urls = new URL[2];
urls[0] = new URL(...);
urls[1] = new URL(...);
task.execute(urls);

如果代码失败,请使用 IDE 中的调试功能并返回确切位置。

关于java - 由于异步 Firebase 调用,主线程做了太多工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37532188/

有关java - 由于异步 Firebase 调用,主线程做了太多工作?的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  3. 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您的程序将作为解释器的子进程执行。除

  4. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  7. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  9. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  10. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

随机推荐