2013-05-07 2 views
0

네트워크에서 항상 데이터를 수신해야하는 스레드가 있으며이 데이터를 EditText 개체에 표시하려고합니다.UI 구성 요소를 수정하는 비 UI 스레드

물론, 수신하는 스레드 내에서 UI EditText에 액세스 할 수 없습니다. 내가 읽은 것은 AsyncTask를 사용할 수 있지만 예제를 Painless Threading에서 읽는 것은 UI 구성 요소에 결과를 게시 할 수 있기 전에 데이터 수신을 완료해야한다는 것입니다.

post 또는 postDelayed를 사용할 수 없습니다. 둘 다 UI 스레드를 통해 실행되며 데이터 수신을 차단할 수 없습니다. 항상 데이터를 계속 받아야합니다.

다른 옵션에는 어떤 것이 있습니까?

답변

1

사용 LocalBroadcastManager, 방송의 청취를 시작합니다 텍스트 뷰가 포함 된 활동 :

Intent intent = new Intent(MyActivity.class.getSimpleName()); 
intent.putExtra("actionType", "updateTextView"); 

// Once this is called, your broadcast receiver in MyActivity should receive it and start processing 
LocalBroadcastManager.getInstance(context).sendBroadcast(intent); 

또한으로 기억 : 스레드가 화면을 업데이트 할 필요가 무엇인가를받을 때마다

public class MyActivity extends Activity { 

    private TextView mTextView; 
    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      String action = intent.getStringExtra("actionType"); 
      if(action.equals("updateTextView")){ 
       mTextView.setText("whatever you want to set"); 
      } 
     } 
    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     //Start listening, you can put it on onResume too 
     LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, new IntentFilter(MyActivity.class.getSimpleName())); 
     mTextView = (TextView) findViewById(R.id.something); 
    } 
} 

그래서,이 전화 onDestroy 또는 onPause에서 등록을 취소하십시오.

* 사이드 노트 : 안드로이드 지원 v4 라이브러리를 가져와야하고 Intent.putExtra ("", "") 및 Inteng.getExtra ("");를 사용하여 간단한 String 또는 객체를 의도별로 전달할 수 있습니다.

+0

를 내가 내 질문에 내가 알고 바보 같은데 어떻게 onReceive 메서드에서 내 UI 구성 요소에 액세스 할 수 있습니까? – Fingolfin

+0

음, 어리석은 질문은 없습니다. 일반적으로 MyActivity 클래스에 선언 된 클래스 변수가 있습니다. 코드의 처음 부분을 편집합니다. –

+0

작동 :) :) 여기에 무슨 일이 있었는지 이해하겠습니다. 우리는 기본적으로 하나의 스레드에서 수신하는 데이터를 전체 프로세스로 브로드 캐스팅하고 있으므로이 프로세스 내의 모든 브로드 캐스트 수신기는 인 텐트를 사용하여 catch합니다. 권리? – Fingolfin

0

또 다른 방법은 데이터 리스너 인터페이스를 구현하는 것입니다

class NonUIThread { 
    private NonUIThreadDelegate delegate; //NonUIThreadDelegate can be an interface or an object that has access to your UI thread like an Activity 

    public void setDelegate(NonUIThreadDelegate delegate) { 
     this.delegate = delegate; 
    } 

    private void doSomthing() { 
     //do something and at the end: 
     delegate.someMethodThatUpdatesThatComponent(); 
    } 
} 

class TheUIThread implements NonUIThreadDelegate /*assuming you've decided to make NonUIThreadDelegate an interface*/ { // the "delegator" 
    /* 
    your code 
    */ 

    private void initiateNonUIThread() { 
     NonUIThread nonUIThread; 
     /*do whatever needed*/ 
     nonUIThread.setDelegate(this); 
     nonUIThread.start(); 
    } 

    public void someMethodThatUpdatesThatComponent() { //will be called by the non ui thread 
     //update the UI 
    } 
} 

그것은 조금 더 나은 여기에 (물론 AsincTask 사용) 설명입니다.

public interface DataListener{ 
    void onUpdateData(MyData data); 
} 

업데이트해야하는 UI 구성 요소가 포함 된 활동은이 인터페이스를 구현합니다. 업데이트 된 데이터로 수행해야 할 작업을 지정합니다. 모든 인스턴스를 이러한 데이터 수신기 인터페이스를 앱의 어딘가에 유지할 수 있습니다. 네트워크 송수신 작업을 처리 할 다른 스레드가 있다고 가정합니다. 데이터 수신시 다음을 호출하십시오.

dataListenerInstance.onUpdateData(data) 

그러면 활동에 구현 한 처리기가 활성화됩니다.

0
MainActivity 호에서

AsyncTask를 확인하지만 @Override 방법 onPostExecute (..)

public class MainActivity extends ActionBarActivity{ 
    ... 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     if(Utils.isNetworkAvailable(this)) { 
      DownloadFileFromURL downloader = new DownloadFileFromURL(){ 
       @Override 
       protected void onPostExecute(Integer file_content) { 
            onCompleteLoad(); 
           } 
          }; 
       downloader.execute(new String[]{file_url, fileName}); 

       ... 

onCompleteLoad(); - MainActivity의 UI 스레드를 호출합니다. Interface를 구현할 필요조차 없습니다!

SECON 방법 서버 솔루션에 더 적합 할뿐만 아니라 클라이언트에서 사용할 수는 호출 가능하다

public class DoGetSize implements Callable<Integer> { 
    private final String file_url; 
    private int lenghtOfFile = -1; 

    public DoGetSize(String file_url) { 
     this.file_url = file_url; 
    } 

    public Integer call() { 
     try { 
      URL url = new URL(file_url); 
      URLConnection connection = url.openConnection(); 
      connection.connect(); 
      lenghtOfFile = connection.getContentLength(); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return lenghtOfFile; 
    } 
} 

그리고 전화 같은 : 당신은

FutureTask<Integer> task = new FutureTask(new DoGetSize(file_url)); 
    ExecutorService es = Executors.newSingleThreadExecutor(); 
    es.submit (task); 
    try { 
     Integer result = task.get(); 
     File file = new File(fileName); 
     if(file.length() != result.intValue()) { 
      // Do something 
      ... 
     } 

    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } 

을 보낼 수에서 물건을받을

전체 예제는 GitHub의에서 볼 수있는 방식 : https://github.com/app-z/OffLineShop/blob/master/app/src/main/java/net/appz/offlineshop/offlineshop/MainActivity.java

관련 문제