2

私は奇妙な問題を抱えており、何か間違ったことをしているのか、それとも何かをしているのかわかりません。何らかの理由で、私の AsyncTask は doInBackground を呼び出さず、onPostExecute() を呼び出します。この AsyncTask が呼び出されることが不可欠です。これは、アプリの残りの部分で必要になる変数を初期化するためです。

メイン アクティビティに、AsyncTask を拡張するネストされたクラスがあります。このクラスは、ユーザーの Dropbox アカウントからファイル名をダウンロードします。

protected class FilesLister extends AsyncTask<String, Integer, Long>
{
    @Override
    protected Long doInBackground(String... params)
    {
        Log.i("Entries", "We believe Entries has some values now.");
        ArrayList<Entry> theFiles = new ArrayList<Entry>();
        try
        {
            Entry entries = mDBApi.metadata("/", 20000, null, true, null);
            for (Entry e : entries.contents)
            {
                Log.i("Hm", e.fileName());
                if (!e.isDeleted)
                {
                    if(!e.isDir)
                    {
                        theFiles.add(e);
                    }
                }
            }
            theEntries = theFiles.toArray(new Entry[theFiles.size()]);
        } catch (DropboxException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return null;
    }

    protected void onPostExecute(Long result)
    {
        super.onPostExecute(result);
        Log.i("Now", "Calling refresh.");
        refresh();
    }
}

ご覧のとおり、onPostExecute は refresh() というメソッドを呼び出します。refresh() は次のように実装されています。

public void refresh()
{
    //Sort all this files by last modified date.
    Arrays.sort(theEntries, new Comparator<Entry>()
    {
        @Override
        public int compare(Entry firstFile, Entry secondFile)
        {
            //"EEE, dd MMM yyyy kk:mm:ss ZZZZZ"
            SimpleDateFormat formater = new SimpleDateFormat("EEE, dd MMM yyyy kk:mm:ss ZZZZZ");
            try
            {
                Date date1 = (Date)formater.parse(firstFile.modified);
                Date date2 = (Date)formater.parse(secondFile.modified);
                return date1.compareTo(date2);
            } catch (ParseException e1)
            {
                e1.printStackTrace();
            }
            return 0;
        }
    });
    //Now we create a String[] array to hold the names of all the fetched files...
    ArrayList<String>txtFilesNames = new ArrayList<String>();
    for(int i = theEntries.length - 1; i >= 0; i--)
    {
        //Loops goes from top to bottom so the latest file appears at the top of the ListView.
        txtFilesNames.add(theEntries[i].fileName());
    }
    actualFileNames = txtFilesNames.toArray(new String[txtFilesNames.size()]);
    ArrayAdapter<String> ad = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, actualFileNames);
    lv.setAdapter(ad);
}

refresh() が呼び出されている理由は 2 つあります。LogCat は「Calling refresh」をログに記録します。その後、NullPointerException が原因でアプリがクラッシュします。theEntries が実際に null であるため、null ポインター例外がスローされ、doInBackground() が呼び出されない限り null になります。また、null ポインターが原因で doInBackground が呼び出されることはなく、本体に配置したログが呼び出されることはないこともわかっています。では、doInBackground() メソッドが呼び出されない原因は何でしょうか? 問題があれば、onResume メソッドで AsyncTask を実行し、onCreate または onStart で他の AsyncTask を実行しません。

4

3 に答える 3

1

doInBackground が呼び出されていないことは確かですか? theEntries を null にする方法は他にもたくさんあります。たとえば、次の例外があります。

        Entry entries = mDBApi.metadata("/", 20000, null, true, null);
        for (Entry e : entries.contents)
        {
            Log.i("Hm", e.fileName());
            if (!e.isDeleted)
            {
                if(!e.isDir)
                {
                    theFiles.add(e);
                }
            }
        }

theEntries が null になる可能性があります。また、これをより良い方法で行うことができると思います。doInBackground (オブジェクトが作成されたスレッドとは別のスレッドにあります) 内で theEntries を設定する代わりに、その関数が onPostExecute に渡すエントリを返すようにする必要があります。コードは次のようになります。

protected class FilesLister extends AsyncTask<String, Integer, Entry[]>
{
    @Override
    protected Entry[] doInBackground(String... params)
    {
        Log.i("Entries", "We believe Entries has some values now.");
        Entry[] entriesReturn = null;
        ArrayList<Entry> theFiles = new ArrayList<Entry>();
        try
        {
            Entry entries = mDBApi.metadata("/", 20000, null, true, null);
            for (Entry e : entries.contents)
            {
                Log.i("Hm", e.fileName());
                if (!e.isDeleted)
                {
                    if(!e.isDir)
                    {
                        theFiles.add(e);
                    }
                }
            }
            entriesReturn = theFiles.toArray(new Entry[theFiles.size()]);
        } catch (DropboxException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        return entriesReturn;
    }

    protected void onPostExecute(Entry[] result)
    {
        super.onPostExecute(result);
        Log.i("Now", "Calling refresh.");
        refresh(result);
    }
}

次に、refresh メソッドで割り当てを行います。また、refresh メソッドで null を確認する必要があります。

于 2012-06-15T19:56:08.330 に答える
0

この方法で、onPostExecute() で doInBackground() が呼び出されているかどうかを確認できます。

 protected Long doInBackground(String... params)
    {
   /////your code...
        return 200;
    }
  protected void onPostExecute(Long result)
    {
       if(result==200)
{
        super.onPostExecute(result);
        Log.i("Now", "Calling refresh.");
        refresh();
}
    }

あなたのエントリが null 値を与えるかどうかはわかりません。このようにして、doInBackground() が実行されているかどうかを知ることができます。

私はそれがいくらかの助けになると思います。

ありがとう。

于 2012-06-15T19:54:16.147 に答える
0

この問題は他の人によって投稿されています (関連する質問についてはサイドバーを参照してください)。現在のところ、この問題の解決策はまだありません。私はこれに遭遇し、数日間苦労した後、これをバグとして受け入れました。あなたができることは使用することですActivity.runOnUiThread()。あなたが抱えているこの問題は修正されますが、 の問題は修正されませんAsyncTasks。それが私がこの問題を回避した方法です。

于 2012-06-15T19:52:05.433 に答える