Модераторы: javastic, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> ожидание загрузки 
:(
    Опции темы
kazna4ey
Дата 19.6.2007, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 7.3.2007

Репутация: нет
Всего: нет



Есть сетевое приложение. При обращении к серверу и скачивании с него файла на дисплей должен выводиться экран ожидания с подвижным элементом (индикатор загрузки). Проблема в том, что метод скачивания запускается в отдельном потоке (иначе никак), но при это основной поток мидлета ждет завершения работы этого метода, и отрисовка экрана ожидания идет только после получения файла, даже если прописать отрисовку до вызова метода скачивания. Долго бился, но ничего не получается, может кто подскажет...
PM MAIL   Вверх
Antropoid
Дата 19.6.2007, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 786
Регистрация: 1.6.2006
Где: &Ukraine==Ode ssa

Репутация: 13
Всего: 16



Цитата(kazna4ey @  19.6.2007,  17:15 Найти цитируемый пост)
 даже если прописать отрисовку до вызова метода скачивания

а если при этом закомметировать вызов потока, который обращается к серверу, - прорисовка работает?

как вариант, - делай прорисовку тоже в отдельном потоке


--------------------
user posted image
Задыхаясь от восторга заниматься чепухой. 
PM MAIL   Вверх
javastic
Дата 20.6.2007, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1214
Регистрация: 18.3.2005
Где: St.Petersburg

Репутация: 19
Всего: 27



Antropoid, прав. Вызывай прорисовку в отдельном потоке который будет запущен из потока скачивания.


--------------------
01101010 01100001 01110110 01100001 01110011 01110100 01101001 01100011
scjp, mcp 
PM MAIL WWW ICQ   Вверх
nagliyvred
Дата 20.6.2007, 14:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 2.10.2005

Репутация: 3
Всего: 3



А если как-нибудь так?
Код

boolean connectionAccomplished = false;

.... 
new Thread()
{
public void run()
{
      connectionAccomplished = false;
      // здесь соединение
      // здесь оно закончилось
      connectionAccomplished = true;
}
}.start();

while (!connectionAccomplished)
{
 canvas.repaint();
 serviceRepaints(); // ну это уже опционально
 try
{ 
  Thread.currentThread().sleep(300);
 } 
catch (InterruptedException ie) { }
}

// дальнейшие действия

PM   Вверх
Dancer
Дата 20.6.2007, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 29.4.2005
Где: Nizhniy Novgorod

Репутация: 33
Всего: 37



nagliyvred, рабоать будет, но за такой код, я бы "убил" на месте!


--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
nagliyvred
Дата 20.6.2007, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 2.10.2005

Репутация: 3
Всего: 3



Цитата(Dancer @ 20.6.2007,  17:02)
nagliyvred, рабоать будет, но за такой код, я бы "убил" на месте!

за что именно?
PM   Вверх
W0LF
Дата 20.6.2007, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


alexander lonsky
***


Профиль
Группа: Участник
Сообщений: 1164
Регистрация: 9.2.2006
Где: Ukraine.Dnepropet rovsk

Репутация: 19
Всего: 20



Код

public abstract class ActionThread implements Runnable {
    private Thread thread;
    protected ScreenManager scrManager;
    private boolean cancelAction = false;
    private LoadingScreen ls; 
    public ActionThread() {
        scrManager = ScreenManager.getInstance();
        thread = new Thread(this);
        thread.start();
    }

    public void run() {        
        changeScreenLoading();
        Model model = Model.getInstance();
        try {
            try {
                NetManager.buildGetAdStringRequest("uuid");
                ActionManager.saveAdsData(model.getTmpAdsData(), model.getTmpAdsLink());
            } catch (IOException ioe) {
                Logger.logError("ActionThread, buildGetAdAdsRequest", ioe.getMessage());
            }
            buildRequest();//посылает запрос, получает ответ, парсит 
                                    //его и заносит в модель результат
        } catch (IOException ioe) {
            String errorMessage = GenerateErrorMessage.getErrorMessage(ioe.getMessage());
            Logger.logError(getClass().getName(), errorMessage);
            if (!cancelAction) {
                ls.clean();
                scrManager.replaceScreen(new ErrorScreen(errorMessage));
                return;
            }
        }
        if (!cancelAction) {
            ls.clean();
            setNextScreen();
        }
    }

    public void setCancelAction(boolean b) {
        cancelAction = b;
    }

    private void changeScreenLoading() {
        synchronized (actionThreadMonitor) {
            ls = new LoadingScreen(this);
            scrManager.pushScreen(ls);
            try {
                actionThreadMonitor.wait();
            } catch (InterruptedException ie) {
                Logger.logError(getClass().getName(), "" + ie);
            } 
        }
    }

    protected abstract void buildRequest() throws IOException;

    protected abstract void setNextScreen();

    private final Object actionThreadMonitor = new Object();

    public Object getActionThreadMonitor() {
        return actionThreadMonitor;
    }
}


public class LoadingScreen extends Canvas implements Runnable {
    private ActionThread actionThreadMonitor;
    public LoadingScreen(ActionThread actionThreadMonitor) {
        try {
            f[0] = Image.createImage("/img/earth/f1.png");
            f[1] = Image.createImage("/img/earth/f2.png");
            f[2] = Image.createImage("/img/earth/f3.png");
            f[3] = Image.createImage("/img/earth/f4.png");
            f[4] = Image.createImage("/img/earth/f5.png");
            f[5] = Image.createImage("/img/earth/f6.png");
            f[6] = Image.createImage("/img/earth/f7.png");
            f[7] = Image.createImage("/img/earth/f8.png");
        }
        catch (IOException ioe) {
            Logger.logError(getClass().getName(), "Can't load earth pictures"
                    + ioe.getMessage());
        }
        this.actionThreadMonitor = actionThreadMonitor;  
        startThread();
    }

    public void paint(Graphics g) {
        g.setFont(fnt);
        g.setColor(0xFFFFFF);
        g.fillRect(0, 0, clientWidth, clientHeight);
        g.setColor(0x000040);
        String loadingString = "LOADING...";
        g.drawImage(f[cimage], clientWidth - 22, 1, Graphics.TOP | Graphics.LEFT);
    }

    public void run() {
        synchronized (actionThreadMonitor.getActionThreadMonitor()) {
            actionThreadMonitor.getActionThreadMonitor().notify();
        }
        while (tLive) {
            try {
                cimage++;
                if (cimage > 7) {
                    cimage = 0;
                }
                Thread.sleep(80);
                repaint();
            }
            catch (InterruptedException ie) {
                Logger.logError(getClass().getName(), "run method - Thread.sleep()"
                        + ie.getMessage());
            }
        }
    }

 

    private void startThread() {
        tLive = true;
        thread = new Thread(this);
        thread.start();
    }

    public synchronized void clean() {
        tLive = false;
        try {
            thread.join();
        }
        catch (InterruptedException ie) {
            Logger.logError(getClass().getName(), "clean method - thread.join()"
                    + ie.getMessage());
        }
    }
}
//Вот для примера логин - 
public class SendLoginThread extends ActionThread{
    private String login;
    private String password;
    private String network;
    private int messagesPerPage;
    private int pageNumber;

    public SendLoginThread(String login, String password, String network,
                           int messagesPerPage, int pageNumber) {
        this.login = login;
        this.password = password;
        this.network = network;
        this.messagesPerPage = messagesPerPage;
        this.pageNumber = pageNumber + 1;
    }

    protected void buildRequest() throws IOException {
        NetManager.buildLoginRequest(login, password, network);
        NetManager.buildGetMessageCountRequest();
        NetManager.buildGetInboxRequest(String.valueOf(messagesPerPage),
                String.valueOf(pageNumber));
    }

    protected void setNextScreen() {
        scrManager.replaceScreen(new InboxScreen());
    }


Все классы взяты со старого кода и подлампичены.. Это так, чтоб увидеть логику. 
НО!!! Это неправильная архитектуа. То есть как бы удобно и просто, для j2me потянет. Но вот для BlackBerry и большой джавы не пойдет. Ибо на самом деле нельзя менять экран из другого потока(нужно ток из главного). Блекберри эксепшн кидает в этом случае.
Еще картинку прилепил как это все наглядно работает.

Присоединённый файл ( Кол-во скачиваний: 22 )
Присоединённый файл  SequenceDiagramLogin.JPG 55,17 Kb


--------------------
iOS developer
PM MAIL WWW Skype GTalk   Вверх
W0LF
Дата 20.6.2007, 18:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


alexander lonsky
***


Профиль
Группа: Участник
Сообщений: 1164
Регистрация: 9.2.2006
Где: Ukraine.Dnepropet rovsk

Репутация: 19
Всего: 20



Цитата(nagliyvred @  20.6.2007,  14:58 Найти цитируемый пост)
А если как-нибудь так?

не факт, что успеет запуститься поток. И твой цикл может ваще не пройти, а поток будет работать

Это сообщение отредактировал(а) W0LF - 20.6.2007, 18:31


--------------------
iOS developer
PM MAIL WWW Skype GTalk   Вверх
Dancer
Дата 20.6.2007, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 29.4.2005
Где: Nizhniy Novgorod

Репутация: 33
Всего: 37



Во-первых, код не безопасен, то есть, в работе этого кода потенциальная бажина!!!
   public void run() {
      connectionAccomplished = false;
      // здесь соединение
Если здесь произойдёт Exception или Error, то у нас всё равно будет перерисовка работать в while(), так как 
connectionAccompished не будет true.
      // здесь оно закончилось
      connectionAccomplished = true;
  }

Во-вторых, пользователю нужно что-то скачать, но это не значит, что нужно после этого разорвать соединение, то есть, соединение будет сохраняться, а закачка уже завершилась, и...,  то есть while() для перерисовки будет работать.....

В-третьих, inner классы (объекты new Thread(){}.start() и т.д.) - это большое зло и достаточно солидная уязвимость для J2ME приложений в частности.
пусть у нас файл Test.java в нём у нас будет что-то вроде такого вот new Thread() то после компиляции у нас получится Test.class Test$1.class можно подменить Test$1.class подделанным и получить доступ к переменным или методам Test.class. С inner классами нужно быть очень аккуратным в использовании.

В-четвёртых, для коннекшена лучше сделать в приложении отдельный класс, и возможно даже абстрактный и добавить ко всему этому менеджер коннекшенов (ну это если нужно и для "будущих периодов" скажем так). Так вот, будет когда у нас менеджер коннекта, мы можем предусмотреть интерфейс специальный, который позволит нам сказать, что происходит закачка и процент закачки такой-то. А компонента (в отдельном потоке), которая должна делать отрисовку будет имплементить метод этого интерфейса и в нём дёргать notify(); repaint(); и потом вызывать у потока wait() тогда мы избавляемся от лишних вызовов в while(). (ну это уже архитектурные изыски скажем так)

Список при желании можно и продолжить, это я накидал сразу, "навскидку" так скажем.


--------------------
У программистов есть великая тайна: всё, что только можно, было давно кем-то когда-то написано. Разработчику только нужно знать в какое место кода какие строчки вставить! smile
PM MAIL   Вверх
nagliyvred
Дата 13.7.2007, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 54
Регистрация: 2.10.2005

Репутация: 3
Всего: 3



Забавно.
Чтож, этот набросок не претендовал на полноценный пример кода. Я поленился и не стал писать кучу кода(каюсь), лишь попробовал подсказать прием, который можно использовать в коде - ждать завершения потока по флагу и при этом перерисовывать экран - по-моему очевидно что тут нет полноценной реализации. Ну да ладно...
Цитата

Цитата(nagliyvred @  20.6.2007,  14:58 Найти цитируемый пост)
А если как-нибудь так?

не факт, что успеет запуститься поток. И твой цикл может ваще не пройти, а поток будет работать

Ну да, для этого переменную нужно обязательно зафолсить перед создаением Thread... 

Цитата

о-первых, код не безопасен, то есть, в работе этого кода потенциальная бажина!!!
   public void run() {
      connectionAccomplished = false;
      // здесь соединение
Если здесь произойдёт Exception или Error, то у нас всё равно будет перерисовка работать в while(), так как 
connectionAccompished не будет true.
      // здесь оно закончилось
      connectionAccomplished = true;
  }

Ну так я же не привел реализацю метода run() целиком! Естественно нужно оборачивать код в try{ } catch() {} особенно если там конекшн, оно без этого и не скомпиляется - run() не должен выбрасывать IOException'ы .

Цитата

Во-вторых, пользователю нужно что-то скачать, но это не значит, что нужно после этого разорвать соединение, то есть, соединение будет сохраняться, а закачка уже завершилась, и...,  то есть while() для перерисовки будет работать.....

Из этого куска вообще никак не следует каким образом мы будем работать с сетью в том потоке. Будет оно сохраняться или нет - это можно легко реализоваать так как нужно.
Цитата

В-третьих, inner классы (объекты new Thread(){}.start() и т.д.) - это большое зло и достаточно солидная уязвимость для J2ME приложений в частности.
пусть у нас файл Test.java в нём у нас будет что-то вроде такого вот new Thread() то после компиляции у нас получится Test.class Test$1.class можно подменить Test$1.class подделанным и получить доступ к переменным или методам Test.class. С inner классами нужно быть очень аккуратным в использовании.

Зло? Возможно. Если плодить их на каждом шагу. Любой метод имеет область и разумные границы применимости. 
А то что Вы пишете про безопасность это вообще извращение. Если программа работает с каким-нибудь web-money через https или с чем другим ( и ее вообще есть смысл зачем-то ломать) то да, Вы несомненно правы. Но к таким приолжениям вообще требования безопасности совсем другие. К чему такие параноидальные мысли в "рядовых" приложениях которые вообще непонятно зачем ломать?) 
Цитата

В-четвёртых, для коннекшена лучше сделать в приложении отдельный класс, и возможно даже абстрактный и добавить ко всему этому менеджер коннекшенов (ну это если нужно и для "будущих периодов" скажем так). Так вот, будет когда у нас менеджер коннекта, мы можем предусмотреть интерфейс специальный, который позволит нам сказать, что происходит закачка и процент закачки такой-то. А компонента (в отдельном потоке), которая должна делать отрисовку будет имплементить метод этого интерфейса и в нём дёргать notify(); repaint(); и потом вызывать у потока wait() тогда мы избавляемся от лишних вызовов в while(). (ну это уже архитектурные изыски скажем так)

Да, так можно сделать. И лучше. Мой метод не претендует на идеальность! Я вешал рекламу "Делайте так везде! Даешь этот способ в массы!" и прочее=) 
А список  продолжайте..  Хотелось бы все-таки выяснить до конца достоинства-недостатки. Чтобы можно было делать так, когда это разумно сделать, и избегать этого ,когда этот способ неподходит
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса

  • Прежде чем задать вопрос прочтите это!
  • Литература по Java находится здесь.
  • Литературу по Java обсуждаем здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит" (возле кнопок кодов) если у Вас нет русских шрифтов.
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда

  • FAQ раздела лежит здесь!
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java ME (J2ME) | Следующая тема »


 




[ Время генерации скрипта: 0.0542 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.