7

我正在玩 android,我正在创建一个简单的 twitter 应用程序来测试我到目前为止学到的东西。但是我遇到了一个我不明白的问题。我创建了一个线程来获取推文,那里没有问题,但随后添加了一个 ProgressDialog 以显示该线程何时运行。这样做会导致非常不寻常的行为。如果用户从垂直方向旋转到水平方向,程序会按预期运行,没有问题,但如果他然后旋转回来,程序会崩溃,说窗口泄漏。

该问题仅发生在水平到垂直布局切换上。我知道如果您在对话框运行时尝试旋转会出现问题,但我已确保对话框已完成运行并在旋转前关闭,但它仍然会崩溃。这是我的代码:

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;
      }


  }
}

这是它崩溃的 LogCat:

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 com.android.internal.policy.impl.PhoneWindow$DecorView@43af9490 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 com.android.internal.policy.impl.PhoneWindow$DecorView@43af9490 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
4

1 回答 1

9

日志中的 WindowLeaked 异常通常发生在您有某种异步任务在开始它的活动被销毁后完成时。

当您旋转屏幕时,将重新创建活动。根据Android 文档,您应该在 onPause 方法中保存所有实例状态,包括确保停止所有异步任务。您可以使用保存的包在 onCreate 方法中重新创建。

于 2010-02-10T21:52:29.717 回答