【问题标题】:Respond Keyboard while Updating UI更新 UI 时响应键盘
【发布时间】:2016-06-09 08:38:30
【问题描述】:

我正在使用android.support.v7.widget.SearchView,并且我在 SearchView 中输入每个字符时执行搜索。以下是sn-p。

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
            {

                @Override
                public boolean onQueryTextSubmit(String query)
                {
                    return false;
                }

                @Override
                public boolean onQueryTextChange(String newText)
                {

                    if (!newText.trim().equals(""))
                    {
                     displayResult(newText);
                    return false;
                   }
              }
            });

当我获取结果时我正在更新 UI,所以在我的情况下,每次用户输入单个字符时它都会调用 Search API。因此,假设用户想要搜索“澳大利亚”并尝试输入整个单词,但我的 UI 正在使用搜索进行更新,并且用户在键盘没有响应后键入“Aus”,因为它正在更新 UI。

所以我只想在更新 UI 时响应键盘。
希望我能得到快速响应。

【问题讨论】:

  • UI更新代码在哪里?请在这里显示
  • 如果您的键盘响应时间较长,则说明您的 UI 更新操作过于繁重。因此键盘需要时间来响应。

标签: android performance android-keypad android-search


【解决方案1】:

你的情况是:

  1. 输入文字

  2. 执行搜索

  3. 显示结果

  4. 再做一次

由于 (2) + (3) 花费了很多时间来完成,所以发生了滞后。

尝试将搜索键从 (1) 发送到工作线程(AsyncTask、Thread、IntentService...)。

(2) 将在工作线程上执行,然后将结果推送回 UI

(3) 更新用户界面

为了提高性能,我认为您应该在用户停止输入时执行搜索。此外,如果输入发生更改,请停止不必要的搜索。

示例:input1 > search1 > input2 > 取消旧任务1 > search2 > ...

希望对您有所帮助!

【讨论】:

    【解决方案2】:

    问题的关键是使用 Search API 的结果更新 UI 操作和使用键盘响应 SearchView 都在 Main(UI) 线程中完成其工作。

    总之,你让主线程在短时间内做了太多事情。

    所以解决方法是尝试LIMIT更新UI操作的频率。我的意思是,你应该让displayResult(newText)方法在用户短时间内连续输入单词时CANCEL之前的调用。

    当整个单词 Australia 被完整输入时,只需使用结果 ONCE 更新 UI。

    顺便说一句,您的搜索 API 调用应该在后台线程中使用一些很棒的库(Retrofit && OkHttp)。

    【讨论】:

      【解决方案3】:

      您可能做错了两件事。 1) 网络请求从 UI Thread 执行 2) 在 UI Thread 上完成解析 从你的stackoverflow点来看,你可能没有做第一种情况,即;在 UI 线程上执行网络请求。

      对于案例2:尝试在后台线程上进行解析,尝试缩短json响应(告诉Search API的作者给出轻量级响应)。 并为每个查询更改取消上一个任务

      【讨论】:

        【解决方案4】:

        您的键盘没有响应,因为 displayResult 方法正在您的主 ui 线程上执行。

        正确处理此问题的一种可能解决方案是使用IntentService,例如,您可以这样做:

        MyIntentService.java

        public class MyIntentService extends IntentService {
        
            //Each of these results represent a possible status of your service
            public static final int RESULT_ERROR = -1;
            public static final int RESULT_ENDED = 1;
            public static final int RESULT_START = 0;
        
            public static final String SERVICE_BROADCAST = MyIntentService.class.getName()+".Broadcast";
        
        
            public MigrateService(){
                super(MigrateService.class.getName());
            }
        
        
            @Override
            protected void onHandleIntent(Intent intent) {
        
                //Get the query
                String queryText = intent.getStringExtra("MyQuery");
        
                //Notify the activity that search has started
                publishResult(RESULT_START, Bundle.EMPTY);
                Bundle data = null;
                try{
                    data = getDataWithRetrofit(queryText);
                } catch (SomeException e){
                    //In case of error, notify the activity
                    publishResult(RESULT_ERROR, Bundle.EMPTY);
                }
                //Search is ended
                publishResult(RESULT_ENDED, data);
            }
        
            public void publishResult(int resultCode, Bundle data){
                Intent intent = new Intent(SERVICE_BROADCAST);
                intent.putExtras(data);
                intent.putExtra("resultCode",resultCode);
                sendBroadcast(intent);
            }
        }
        

        基本上,您有一个Service,它在后台线程中获取数据并在某些事件发生(开始/结束)时将数据发送到您的Activity。

        在您的 Activity 课程中,您需要执行以下操作:

        1.声明一个BroadcastReceiver 实例:

        private BroadcastReceiver mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if(intent.hasExtra("resultCode")) {
                    int resultCode = intent.getIntExtra("resultCode",MyService.STATUS_ERROR);
                    switch (resultCode) {
                        case MyIntentService.RESULT_START:
                            showIndeterminateProgress();
                            break;
                        case MyIntentService.RESULT_ENDED:
                            updateResultList(data);
                            break;
                        case MyIntentService.RESULT_ERROR:
                            showErrorMessage();
                            break;
                    }
                }
            }
        };
        

        2。注册和注销您的BroadcastReceiver:

        @Override
        public void onResume(){
            super.onResume();
            registerReceiver(mReceiver, new IntentFilter(MyIntentService.SERVICE_BROADCAST));
        }
        
        @Override
        public void onPause() {
            super.onPause();
            unregisterReceiver(mReceiver);
        }
        

        3.启动您的服务:

        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener()
            {
                @Override
                public boolean onQueryTextSubmit(String query)
                {
                    return false;
                }
                @Override
                public boolean onQueryTextChange(String newText)
                {
                    if (!newText.trim().equals(""))
                    {
                        Intent i = new Intent(this, MyIntentService.class);
                        i.putExtra("MyQuery",newText);
                        startService(i);
                        return false;
                    }
                }
            });
        

        来源:

        【讨论】:

          【解决方案5】:

          在其 afterTextChanged 方法中使用 TextWatcher 编写您的搜索查询并从那里调用刷新您的视图本身。 此外,使用异步方式进行 API 调用,这样您的 UI 就不会卡住,您可以在 refreshView 方法中加载响应。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-07-11
            • 2011-11-28
            • 1970-01-01
            • 2014-08-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多