2010-02-10 3 views
7

나는 안드로이드로 놀고있어, 지금까지 배운 것을 테스트하기 위해 간단한 트위터 앱을 만들고있다. 그러나 나는 이해하지 못하는 문제를 겪었다. 트윗을 가져오고 문제가없는 스레드를 만들었지 만 ProgressDialog를 추가하여 스레드가 실행 중일 때 표시했습니다. 그렇게하는 것은 매우 드문 행동을 일으켰습니다. 사용자가 세로 방향에서 가로 방향으로 회전하면 프로그램은 예상대로 동작하지만 아무런 문제가 없지만 다시 회전하면 프로그램이 충돌하여 창이 누출되었다고 말합니다.Android : 회전시 충돌, 수직에서 수평

문제는 가로형에서 세로 형 레이아웃 스위치에서만 발생합니다. 대화 상자가 실행되는 동안 회전하려고하면 대화 상자가 실행을 완료하고 회전하기 전에 닫히고 여전히 충돌 할 것이라는 점을 확인했습니다. Heres는 내 코드 : heres는

package com.onesmartpuppy.puppytweet; 
import java.util.ArrayList; 
import com.github.droidfu.widgets.WebImageView; 
import winterwell.jtwitter.Twitter; 
import winterwell.jtwitter.Twitter.Status; 
import android.app.ListActivity; 
import android.app.ProgressDialog; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.View.OnClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.TextView; 

public class PuppyTweet extends ListActivity implements OnClickListener { 

    private ProgressDialog m_ProgressDialog = null; 
    private ArrayList<Status> messages = null; 
    private TweetAdapter m_adapter; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     messages = new ArrayList<Status>(); 
     this.m_adapter = new TweetAdapter(this, R.layout.row, messages); 
     setListAdapter(this.m_adapter); 

     setupButtons(); 

     m_ProgressDialog = ProgressDialog.show(this,  
      "Please wait...", "Retrieving tweets ...", true); 

     Runnable findTweets = new Runnable(){ 
      @Override 
      public void run() { 

      try { 
       messages = new ArrayList<Status>(); 

       Twitter ourTwitter = new Twitter("*****", "******"); 
       messages = (ArrayList<Status>) ourTwitter.getFriendsTimeline(); 

       Thread.sleep(1000); 
       Log.i("ARRAY", ""+ messages.size()); 
      } catch (Exception e) { 
       Log.e("BACKGROUND_PROC", e.getMessage()); 
      } 
       handler.sendEmptyMessage(0); 
      } 
     }; 

     Thread thread = new Thread(null, findTweets, "FindTweets"); 
     thread.start(); 
    } 



    private void setupButtons() 
    { 
    Button refreshButton = (Button) findViewById(R.id.refresh_button); 
    refreshButton.setOnClickListener(this); 
    Button settingsButton = (Button) findViewById(R.id.settings_button); 
    settingsButton.setOnClickListener(this); 
    Button tweetButton = (Button) findViewById(R.id.update_button); 
    tweetButton.setOnClickListener(this); 
    } 



@Override 
public void onClick(View v) { 
    switch (v.getId()) 
    { 
    case R.id.settings_button: 
    break; 
    case R.id.update_button: 
    break; 
    case R.id.refresh_button: 
    break; 
    default: 
    break; 
    } 
} 

private Handler handler = new Handler() { 

     @Override 
     public void handleMessage(Message msg) { 
      if(messages != null && messages.size() > 0){ 
       m_adapter.clear(); 
       m_adapter.notifyDataSetChanged(); 
       for(int i=0;i<messages.size();i++) 
        m_adapter.add(messages.get(i)); 
      } 
      m_ProgressDialog.dismiss(); 
      m_adapter.notifyDataSetChanged(); 
     } 
    }; 


    private class TweetAdapter extends ArrayAdapter<Status> { 

     private ArrayList<Status> items; 

     public TweetAdapter(Context context, int textViewResourceId, ArrayList<Status> items) { 
       super(context, textViewResourceId, items); 
       this.items = items; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
       View v = convertView; 
       if (v == null) { 
        LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
        v = vi.inflate(R.layout.row2, null); 
       } 
       Status o = (Status) items.get(position); 

       if (o != null) { 
       WebImageView img = (WebImageView) v.findViewById(R.id.webimage);     
         TextView tt = (TextView) v.findViewById(R.id.toptext); 
         TextView bt = (TextView) v.findViewById(R.id.bottomtext); 
         if (tt != null) { 
          tt.setText("Name: " + o.user.name);       } 
         if(bt != null){ 
          bt.setText("Status: " + o.getText()); 
         } 
         if (img !=null) { 
         img.setImageUrl(o.getUser().profileImageUrl.toString()); 
          img.loadImage(); 
         } 
       } 
       return v; 
     } 


    } 
} 

가 충돌 곳에서 로그 캣 : 당신이 시작 활동 후 마무리되는 비동기 작업의 일종이있을 때

02-10 16:01:05.237: INFO/ActivityManager(63): Config changed: { scale=1.0 imsi=310/260 loc=ld_US touch=3 keys=2/1/2 nav=3/1 orien=2 layout=18} 
02-10 16:01:05.344: WARN/UsageStats(63): Something wrong here, didn't expect com.onesmartpuppy.puppytweet to be resumed 
02-10 16:01:05.384: INFO/WindowManager(63): Setting rotation to 0, animFlags=0 
02-10 16:01:05.394: INFO/ActivityManager(63): Config changed: { scale=1.0 imsi=310/260 loc=ld_US touch=3 keys=2/1/2 nav=3/1 orien=1 layout=18} 
02-10 16:01:05.504: WARN/UsageStats(63): Something wrong here, didn't expect com.onesmartpuppy.puppytweet to be resumed 
02-10 16:01:05.704: ERROR/WindowManager(227): Activity com.onesmartpuppy.puppytweet.PuppyTweet has leaked window [email protected] that was originally added here 
02-10 16:01:05.704: ERROR/WindowManager(227): android.view.WindowLeaked: Activity com.onesmartpuppy.puppytweet.PuppyTweet has leaked window [email protected] that was originally added here 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.view.ViewRoot.<init>(ViewRoot.java:227) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.view.Window$LocalWindowManager.addView(Window.java:424) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.Dialog.show(Dialog.java:239) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ProgressDialog.show(ProgressDialog.java:107) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ProgressDialog.show(ProgressDialog.java:90) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at com.onesmartpuppy.puppytweet.PuppyTweet.onCreate(PuppyTweet.java:39) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2470) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3573) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.access$2300(ActivityThread.java:119) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1825) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.os.Handler.dispatchMessage(Handler.java:99) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.os.Looper.loop(Looper.java:123) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.main(ActivityThread.java:4310) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at java.lang.reflect.Method.invokeNative(Native Method) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at java.lang.reflect.Method.invoke(Method.java:521) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at dalvik.system.NativeStart.main(Native Method) 
02-10 16:01:06.344: INFO/global(227): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required. 
02-10 16:01:06.624: DEBUG/dalvikvm(227): GC freed 6082 objects/479568 bytes in 77ms 
02-10 16:01:07.374: DEBUG/dalvikvm(227): GC freed 11982 objects/709808 bytes in 83ms 
02-10 16:01:07.394: INFO/global(227): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required. 
02-10 16:01:07.564: DEBUG/dalvikvm(227): GC freed 95 objects/79880 bytes in 68ms 
02-10 16:01:07.704: DEBUG/dalvikvm(227): GC freed 8 objects/38992 bytes in 65ms 
02-10 16:01:08.174: DEBUG/dalvikvm(63): GC freed 5407 objects/257208 bytes in 174ms 
02-10 16:01:08.194: INFO/ARRAY(227): 20 
02-10 16:01:08.204: DEBUG/AndroidRuntime(227): Shutting down VM 
02-10 16:01:08.204: WARN/dalvikvm(227): threadid=3: thread exiting with uncaught exception (group=0x4001b188) 
02-10 16:01:08.204: ERROR/AndroidRuntime(227): Uncaught handler: thread main exiting due to uncaught exception 
02-10 16:01:08.214: ERROR/AndroidRuntime(227): java.lang.IllegalArgumentException: View not attached to window manager 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:200) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.view.Window$LocalWindowManager.removeView(Window.java:432) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.Dialog.dismissDialog(Dialog.java:280) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.Dialog.access$000(Dialog.java:73) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.Dialog$1.run(Dialog.java:109) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.Dialog.dismiss(Dialog.java:264) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at com.onesmartpuppy.puppytweet.PuppyTweet$1.handleMessage(PuppyTweet.java:104) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.os.Handler.dispatchMessage(Handler.java:99) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.os.Looper.loop(Looper.java:123) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.ActivityThread.main(ActivityThread.java:4310) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at java.lang.reflect.Method.invokeNative(Native Method) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at java.lang.reflect.Method.invoke(Method.java:521) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at dalvik.system.NativeStart.main(Native Method) 
02-10 16:01:08.244: INFO/Process(63): Sending signal. PID: 227 SIG: 3 
02-10 16:01:08.244: INFO/dalvikvm(227): threadid=7: reacting to signal 3 
02-10 16:01:08.274: ERROR/dalvikvm(227): Unable to open stack trace file '/data/anr/traces.txt': Permission denied 
02-10 16:01:08.754: DEBUG/dalvikvm(227): GC freed 5986 objects/372656 bytes in 316ms 
02-10 16:01:09.829: INFO/ARRAY(227): 20 
02-10 16:01:09.955: INFO/Process(227): Sending signal. PID: 227 SIG: 9 
02-10 16:01:09.974: INFO/ActivityManager(63): Process com.onesmartpuppy.puppytweet (pid 227) has died. 
02-10 16:01:10.014: INFO/WindowManager(63): WIN DEATH: Window{43b653e0 com.onesmartpuppy.puppytweet/com.onesmartpuppy.puppytweet.PuppyTweet paused=false} 
02-10 16:01:10.014: INFO/WindowManager(63): WIN DEATH: Window{43c32b48 Please wait... paused=false} 
02-10 16:01:10.164: WARN/UsageStats(63): Unexpected resume of com.android.launcher while already resumed in com.onesmartpuppy.puppytweet 
02-10 16:01:10.314: WARN/InputManagerService(63): Got RemoteException sending setActive(false) notification to pid 227 uid 10023 
+2

Android의 * LogCat * 기능을 사용하고 코드 내에'Log' 클래스로 디버깅 문을 남겨두고 Android에서 * LogCat * Perspective 창을 열고 스택 추적을 게시하십시오. 창문 누출이 발생한 줄을 표시하고 문제 해결 방법을 알려줍니다. –

+1

스택 추적이 있습니까? –

+0

그 스레드를 죽일 onDestroy 및 onPause 이벤트를 처리 가치가있을 수 있습니다. 아마도 문제는 아니지만. –

답변

9

로그의 WindowLeaked 예외는 일반적으로 발생 파괴되었다.

화면을 회전하면 활동이 재생성됩니다. Android docs 당 async 작업이 중지되었는지 확인하는 것을 포함하여 onPause 메서드에서 모든 인스턴스 상태를 저장해야합니다. 저장된 번들을 사용하여 onCreate 메서드에서 다시 만들 수 있습니다.

+2

대화 상자의 onPause 메서드에서 dismiss()를 추가하여 모든 문제를 해결했습니다. 감사! – Kelend

+0

이 문제를 더 잘 이해하고 솔루션이 작동하는 이유를 알려 주셔서 감사합니다. 이 문제는 오랫동안 지속되어 왔습니다! 이제는 PreferenceActivity의 onPause()에서 사용자 지정 alertdialog를 해제하기 때문에 WindowLeak가 없습니다. 대화 상자가 표시되어있는 동안 전화가 회전 된 경우에만 발생합니다. –

관련 문제