0

upnp 검색에 cling 라이브러리 사용. 의 deviceDiscovered가 발사 될 때마다, 다음 코드를 호출하면 아래와 같이 notifyDataSetChangedAndroid viewpager notifyDataSetChanged가 IllegalStateException을 발생시킵니다.

public void deviceAdded(Registry registry, Device device) { 
     // TODO Auto-generated method stub 
     super.deviceAdded(registry, device); 

     String name = device.getDisplayString(); 
     String manufac = device.getDetails().getManufacturerDetails() 
       .getManufacturer(); 
     if (!manufac.contains("Microsoft")) { 
      if (!deviceNames.contains(name)) { 
       if (!devices.contains(device)) { 
        devices.add(device); 
        deviceNames.add(name); 
        Log.e(TAG,"\t\tdevice.size() = "+String.valueOf(devices.size())); 
       // Log.e(TAG,"Calling notify runnable after adding device "+deviceNames.get(deviceNames.size()-1)); 
        runOnUiThread(notifyAdapterDataChanged); 
       } 

      } 
     } 
} 

ViewPager 필드 선언

ArrayList/*CopyOnWriteArrayList*/<Device> devices; 
    ArrayList/*CopyOnWriteArrayList*/<String> deviceNames; 

notifyAdapterDataChanged이 실행 가능하다 호출, 따라서 항 장치 목록을 업데이트

@Override 
     public void run() { 
      if(adapter != null){ 
       adapter.notifyDataSetChanged(); 
      } 
     } 

아래 예외 발생 중

07-25 02:58:36.185: E/AndroidRuntime(11404): FATAL EXCEPTION: main 
07-25 02:58:36.185: E/AndroidRuntime(11404): java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 5, found: 6 Pager id: com.example.upnpclient/myviewpager Pager class: class android.support.v4.view.ViewPager Problematic adapter: class com.example.upnpclient.MyPagerAdapter 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.support.v4.view.ViewPager.populate(ViewPager.java:967) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.support.v4.view.ViewPager.populate(ViewPager.java:919) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1441) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.View.measure(View.java:15473) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:617) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:399) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.View.measure(View.java:15473) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5056) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.View.measure(View.java:15473) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.widget.LinearLayout.measureVertical(LinearLayout.java:833) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.widget.LinearLayout.onMeasure(LinearLayout.java:574) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.View.measure(View.java:15473) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5056) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2361) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.View.measure(View.java:15473) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1974) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1217) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1390) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1112) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4472) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.Choreographer.doCallbacks(Choreographer.java:555) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.Choreographer.doFrame(Choreographer.java:525) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.os.Handler.handleCallback(Handler.java:615) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.os.Handler.dispatchMessage(Handler.java:92) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.os.Looper.loop(Looper.java:137) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at android.app.ActivityThread.main(ActivityThread.java:4898) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at java.lang.reflect.Method.invokeNative(Native Method) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at java.lang.reflect.Method.invoke(Method.java:511) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773) 
07-25 02:58:36.185: E/AndroidRuntime(11404): at dalvik.system.NativeStart.main(Native Method) 
+0

나는 여기에 해결책이있다. (http : // stackoverflow.com/a/32185084/1239911) – Amt87

답변

3

먼저 번마다 어댑터에서 참조하는 목록에 항목을 추가하면 notifyDataSetChanged으로 전화해야합니다.

UI 스레드가 완료되기 전에 두 번째 항목을 추가하면 보통 상황이 발생합니다. notifyDataChanged. 어댑터를 사용하여 항목을 추가하여이를 방지 할 수 있습니다. 오히려 목록에 아닌 어댑터에 직접 항목을 추가하려면 runOnUIThread가 끝날 때까지

기다려야하는 뮤텍스를 사용할 수 있습니다 -이 같은 :

final Semaphore mutex = new Semaphore(0); 
runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     adapter.notifyDataSetChanged(); 
     mutex.release(); 
    } 
}); 

try { 
    // wait for the line mutex.release(); to be executed 
    mutex.acquire(); 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 

을 지금 추가하는 경우 항목을 목록에 추가하고 UI 스레드를 시작하면 해당 항목을 추가하는 스레드는 UI 스레드가 어댑터에 알리는 것과 함께 수행 될 때까지 대기합니다 (뮤텍스를 통해). 이렇게하면 어댑터가 업데이트되기 전에 추가 항목이 목록에 들어가는 경우가 방지됩니다.

편집 : 또 다른 해결책은 UI 스레드에 항목을 추가하는 것입니다. 그래서 같이 당신의 경우 :

runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      devices.add(device); 
      deviceNames.add(name); 
      adapter.notifyDataSetChanged(); 
     } 
    }); 

이 방법 만 adapter.notifyDataSetChanged(); 호출 당 하나 개의 항목을 추가 여전히 mutex 동안을 피할 수있다.

+0

제약 조건은 '뮤텍스'를 사용하지 않아야합니다. '어댑터를 사용하여 항목을 추가하여 .' 이미 어댑터 (MyPagerAdapter)를 사용하고 있습니다. – nmxprime

+0

왜 제약 조건입니까? 그리고 질문에 왜 그런 말을하지 않습니까? 오리온 (Orion)과 같이'yourlist.Add (name)'대신'adapter.Add (name)'을 사용하는 것이 좋습니다. 이 장치의 발견을 지연 때문에 – ntv1000

+0

는 – nmxprime

0

당신은 여기 보면 : https://stackoverflow.com/a/5092426/1235505

인용구 : 당신은() 추가를 사용하는 경우

ArrayAdapter와 들어

만 작동 notifyDataSetChanged가 (,,) (삽입) (제거, 맑은).

따라서 어댑터를 수동으로 어댑터에 추가하면 데이터를 수정 한 후에 예외가 발생할 수 있습니다.

질문에서 이미이 방법을 사용했는지 알 수 없지만 다음에 필드 선언을 함께 표시해주십시오.

+0

Field declerations와 함께 업데이트 된 질문 – nmxprime

+0

여기 좀보세요 : http://stackoverflow.com/a/6244952/1235505 – Orion

0

어떤 이유로 든 (예 : 다른 앱에 대한 의도를 통해) 활동을 떠나는 경우 활동 아래에 항목 아래에 행을 추가해야합니다.

android:configChanges="keyboardHidden|orientation|screenSize"