2013-09-15 3 views
0

Мне нужно проверить переменную для изменения, если произойдет изменение, я обновлю текстовое представление.Активность android создать несколько экземпляров моего потока

поэтому я создал новую цепочку с петлей while для этой цели. i проверять переменную каждые 1 секунду, через Thread.sleep()

этот поток создан и запущен в onCreate(). так что это один раз.

Проблема заключается в том, что каждый раз, когда я переворачиваю свой телефон (от вертикали до горизонтали или ...), создается новый поток.

вот мой код:

public class HomeActivity extends Activity 
{ 
private final static int LOAD_SUCCESSFULL = 1; 
private final long LOCATION_THREAD_SLEEP = 1000;  
private boolean flag = false; 
static TextView lat; 
static TextView lon;  
static Location currentLocation = null; 
Thread locationThread; 

@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState);   
    requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); 
    setContentView(R.layout.new_home2); 
    this.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.new_home_titlebar); 

    lat = (TextView)findViewById(R.id.t2rt3); 
    lon = (TextView)findViewById(R.id.t2rt4); 

    /* FindLocation class is a helper class that find location via simcard or gps in separate thread, 
     same problem happen with this thread also, it create multiple thread, for ease of work i 
     commented this part. 
    */  
    //FindLocation fn = new FindLocation(this); 

    locationThread = new Thread(null, loadLocation, "loadLocationHomePage"); 

    locationUpdater(); 
} 

private static Handler locationUpdateHandler = new Handler() 
{ 
    public void handleMessage(Message msg) 
    { 
     switch(msg.what) 
     { 
     case LOAD_SUCCESSFULL: 
      lat.setText(Double.toString(currentLocation.getLatitude())); 
      lon.setText(Double.toString(currentLocation.getLongitude())); 
      //stopThread(); 
      break;    
     } 
    } 
}; 

private Runnable loadLocation = new Runnable() 
{ 
    public void run() 
    { 
     //boolean flag = false; 
     while(!flag) 
     { 
      if(Data.currLocation != null) 
      {     
       currentLocation = new Location(Data.currLocation);     
       Message msg = locationUpdateHandler.obtainMessage(LOAD_SUCCESSFULL);      
       locationUpdateHandler.sendMessage(msg); 
       //return; 
       flag = true; 
       //return; 
      }    
      else 
      { 
       try 
       { 
        Thread.sleep(LOCATION_THREAD_SLEEP); 
       } 
       catch (InterruptedException e) 
       { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      }    
     } 
    } 
}; 

public void locationUpdater() 
{ 
    //Thread locationThread = new Thread(null, loadLocation, "loadLocationHomePage"); 
    locationThread.start(); 
} 

так, как я могу решить эту проблему?

enter image description here

+2

Я думаю, что более полезно попытаться объяснить, что вы пытаетесь сделать. Кажется, что вы обновляете глобальную статическую переменную (currentLocation) в другом месте и хотите прочитать это в этой операции. Вместо использования потоков кажется, что вы должны использовать какой-то механизм, чтобы слушатели знали, что новое место будет готово к употреблению. – dmon

+0

@dmon: ok, вы правы, я обновляю статический объект местоположения через класс FindLocation (читайте комментарий в oncreate).то каждый раз, когда обновляется местоположение, я хочу обновить 2 textView (для широты и долготы), поэтому я создал этот поток, чтобы проверить наличие переменных местоположения. – mehdok

+0

@dmon: я не могу найти какой-либо механизм для этого для textview, для listView вы можете сделать это, уведомив() (или что-то вроде этого, я не помню), но для текстового представления нет ничего подобного, так что я делаю это, в любом случае механизм не имеет значения, дело в том, что эта проблема не должна произойти вообще. – mehdok

ответ

1

На самом деле проблема в том, что каждый раз, когда вы переключаете телефон создается новый экземпляр Activity и из-за этого вы на каждом вращении вы получите вызов на onCreate() где вы слепо создаете новый Thread и запустили новый Thread.

Это поведение по умолчанию каждого Activity, но мы можем изменить это воссоздание деятельности, заявив атрибут в AndroidManifest файле для деятельности

<activity 
    android:name="yourPackage.ActivityName" 
    android:configChanges="keyboardHidden|orientation|screenSize" 
</activity> 

Это предотвратит от создания активности в связи с изменением ориентации.

Вы также получите эти ориентации событие, если вы override

@Override 
     public void onConfigurationChanged(Configuration newConfig) {} 

Надеетесь, что это позволит решить эту проблему без внедрения такой сложной логики, которая может сломала в каком-то другое использует случай.

+0

Я получил одобрение, потому что это ответ, по крайней мере, подходящий для новичков, но не рекомендованное решение. –

+0

это может сработать, но в этом случае мне нужно самому обрабатывать ориентацию. Я думаю о создании моего слушателя для извлечения значение – mehdok

+1

@Pork Да, это не рекомендуемое решение, но как вы хотите создать свою систему полностью на руке Я только что дал решение, почему новый экземпляр потока создается при каждом изменении ориентации. вы должны создать класс LocationManager и сделать его как одноэлементный класс, чтобы во всей вашей системе должен был быть только один экземпляр этого управления er, и каждый компонент говорит, что Activity или Services могут использовать этот экземпляр. –

0

Я думаю, что вы не возможно идти об этом в наиболее эффективным способом.

Но если ваш вопрос просто, как я могу предотвратить появление нескольких рабочих потоков, вы должны заглянуть в фрагмент UIless.

http://www.vogella.com/articles/AndroidFragments/article.html#headlessfragments1

+0

Я не мог найти другого эффективного способа решения этой проблемы. знаете ли вы? – mehdok

+0

хорошо, я ответил на ваш вопрос. Я действительно не вижу смысла в том, что в какой-либо другой части приложения было опрошено место. Почему бы просто не использовать диспетчер местоположения и идентификатор местоположения в вашей деятельности или, возможно, снова, без заголовка? –

+0

есть 5 действий, которые нуждаются в этой информации, если я использую locationmanager в каждом действии, поэтому каждое действие пытается найти местоположение, поэтому я создаю этот отдельный класс и делаю это один раз, чтобы любое другое действие могло использовать эту информацию. Другая проблема - чтение местоположения через GPS - это трудоемкий процесс, с помощью которого пользователь может перемещаться по другой активности, в то время как местоположение загрузки GPS в фоновом режиме. – mehdok

0

я не знаю, почему андроид это делать. если я поместил свой код в onResume(), то это поведение будет иметь смысл, но в моем случае я не знаю.

в любом случае я нашел грязное решение. идея заключается в поиске списка всех потоков и поиске их для моего, если он существует, предотвращает создание другого.

public boolean checkThreadExist() 
{ 
    Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); 
    Thread[] threadArray = threadSet.toArray(new Thread[threadSet.size()]); 
    for(int i = 0; i < threadArray.length ; i++) 
    { 
     if(threadArray[i].getName().equalsIgnoreCase("loadLocationHomePage")) 
      return true; 
    } 

    return false; 
} 

обновленный OnCreate():

if(checkThreadExist()) 
    { 

    } 
    else 
    { 
     locationThread = new Thread(null, loadLocation, "loadLocationHomePage");    
     locationUpdater();    
    } 
+0

onCreate вызывается всякий раз, когда происходит изменение конфигурации, когда вы вращаете свой телефон, вся деятельность уничтожается и создается с нуля. Это нормальное поведение. Если вы хотите что-то сохранить, используйте onSaveInstanceState(), и во время oncreate savedInstanceState будут иметь ваши данные из ранее уничтоженного действия ... ИЛИ ... вы используете фрагмент (рекомендуемое решение, если вы выполняете «работу», которая должна сохраняться. –

Смежные вопросы