Въвеждане на клавиатура: изпълнява заявка със закъснение между символите

За да намаля претоварването на сървъра по време на търсене, ще осигуря забавяне за въвеждане от клавиатурата.

случай на използване:
1. потребителят въвежда символи
2. ако забавянето между въвеждането на символи ‹ 1 секунда, това търсене НЕ се изпълнява незабавно и се чака, когато закъснението след последния въведен символ е > 1 секунда
3. ако закъснението между въведените символи е > 1 секунда , това търсене се извърши незабавно

Има ли най-добри практики в JSE или в мобилната Java (Blackberry)?

Изглежда, че трябва да използвам TimerTask и API на таймера за такъв случай. то?


person sergionni    schedule 15.04.2012    source източник


Отговори (2)


Според библията на Java concurrency 'Java concurrency на практика'

... Таймерът има някои недостатъци и ScheduledThreadPoolExecutor трябва да се смята за негов заместител.

Така бих направил нещо като този пример:

public class DelayedSearch extends JFrame {
    public DelayedSearch() {
        final JPanel panel = new JPanel(new BorderLayout());
        final JTextField field = new JTextField(30);
        panel.add(field, BorderLayout.NORTH);
        final JLabel status = new JLabel(" ");
        panel.add(status, BorderLayout.SOUTH);
        this.add(panel);
        this.pack();
        final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        field.addKeyListener(new KeyAdapter() {
            private ScheduledFuture<?> scheduled;
            @Override
            public void keyTyped(KeyEvent e) {
                if (scheduled != null) scheduled.cancel(false);
                scheduled = executor.schedule(new Runnable() {
                    @Override
                    public void run() { // Perform search here. Just set status for demo.
                        status.setText("Search: " + field.getText());
                    }
                }, 1, TimeUnit.SECONDS);
            }
        });
    }
    public static void main(String[] args) {
        new DelayedSearch().setVisible(true);
    }
}

Забележка: Актуализирам състоянието от нишка, различна от EDT тук, което е незаконно, но схващате идеята.

РЕДАКТИРАНЕ: въз основа на страхотни коментари по-долу (благодаря!) Timer ще работи в този прост случай и улеснява използването на демон нишка (въпреки че има проблеми със задачи, които хвърлят изключения, както е описано в книгата). За да направите това, заменете изпълнителя и слушателя по-горе, както следва:

        ...
        final Timer timer = new Timer(true); // use daemon thread.
        field.addKeyListener(new KeyAdapter() {
            private TimerTask task;
            @Override
            public void keyTyped(KeyEvent e) {
                if(task != null)task.cancel();
                task = new TimerTask() {
                    @Override
                    public void run() {
                        status.setText("Search: " + field.getText());
                    }
                };
                timer.schedule(task, 1000);
            }
        });
person Ian Jones    schedule 15.04.2012
comment
Иън, благодаря ти за намека, ще ти дам обратна връзка веднага щом опиташ - person sergionni; 15.04.2012
comment
Според моя работен опит Timer API все още е по-добрият избор за тривиална употреба. Executors API е сложен и всъщност няма какво повече да предложи на прост сценарий. Особено, ако искате вашата нишка на таймера да бъде демон нишка (винаги добра идея за такива прости задачи -- не се изисква изрично почистване), рамката Executors ви принуждава да създадете персонализиран ThreadFactory за това. - person Marko Topolnik; 15.04.2012
comment
@Marko има добра гледна точка относно нишките на демон. Вече имам DaemonThreadFactory в моя проект, който използвам на различни места, така че не гледайте на това като на излишни разходи. Проблемът с Timer дори в този прост пример е, че не можете да отмените задача, можете само да отмените цялата Timer, което означава, че имате нужда от нова (и нова нишка) всеки път. - person Ian Jones; 15.04.2012
comment
@IanJones Но TimerTask може да бъде отменено. До голяма степен е същото като Future в това отношение. - person Marko Topolnik; 15.04.2012
comment
@MarkoTopolnik напълно си прав, моите извинения. Ще актуализирам отговора си. - person Ian Jones; 15.04.2012
comment
въпрос относно условието:if(task != null)task.cancel();доколкото разбирам винаги е null по този въпрос, нали? - person sergionni; 16.04.2012
comment
о, разбрах)) Просто игнорирайте предишния коментар, моля. - person sergionni; 16.04.2012

Да, използвайте TimerTask. Бих предложил допълнителна промяна на вашите правила: просто се уверете, че заявките са разположени на разстояние поне една секунда, но не чакайте, докато потребителят спре да въвежда за секунда. Вместо това веднага след изтичане на времето за изчакване издайте нова заявка със състоянието на полето за въвеждане в този момент. Потребителят може да е по средата на писане, но неговият опит с вашето приложение ще бъде по-плавен и отзивчив.

person Marko Topolnik    schedule 15.04.2012