0

こんにちはみんな、
私は私のAndroid用のチャットクライアントを作りたかったです。しかし、私は接続を取得できません。
まあ、多分あなたは私を少し助けることができます..
私のMainActivity.javaで私は呼び出します:

//connect to the server
SocketTask connection = new SocketTask(this); 
connection.execute();

私のSocketTask.javaは次のようになります。

package chat.client;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

import android.os.AsyncTask;

public class SocketTask extends AsyncTask<Void, Void, Void>{
    private Socket socket;
    private DataInputStream input;
    protected PrintStream output;
    private MainActivity main;
    private Thread thrd;

    public SocketTask(MainActivity main){
        this.main = main;
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            socket = new Socket("192.168.178.23", 1338);
            input = new DataInputStream(socket.getInputStream());
            output = new PrintStream(socket.getOutputStream());

            // submittes the name of the client
            output.println("Mobile");
            output.flush();
            thrd = new Thread(new Runnable() {
                public void run() {
                    while (!Thread.interrupted()) {
                        try {
                            final String data = input.readLine();
                            if (data != null)
                                main.runOnUiThread(new Runnable() {
                                    //new Runnable(){
                                    @Override
                                    public void run() {
                                        if(!data.equals("")){
                                            //main.chatHistory.append(data+"\n");
                                            main.addText(data);
                                        }else{
                                            //chatHistory.append("\n");
                                            main.addText("");
                                        }

                                    }
                                });
                            //};
                        } catch (IOException e) {
                            //chatHistory.append("Verbindung zum Server abgebrochen!");
                            main.addText("Verbindung zum Server abgebrochen!");
                        }
                    }
                }
            });
            thrd.start();
        } catch (Exception e) {
            //chatHistory.append("Es konnte keine Verbindung zum Server aufgebaut werden!");
            main.addText("Es konnte keine Verbindung zum Server aufgebaut werden!"+e);
        }
        return null;
    }
}

しかし、起動すると、次のようになります:
02-27 16:32:05.875:E / SensorManager(26146):スレッド開始

また、「connection.execute()」の代わりに「connection.doInBackground()」を呼び出そうとすると(これはまったく意味がないことはわかっています)、「networkonmainthreadexception」が表示されますが、すでにAsyncTaskでそれを修正しました。ええと、私はAndroidに不慣れですが、私はすでにたくさんグーグルで検索しました。私がそんなに愚かであるかどうかはわかりませんが、今はあきらめて、ここに登録しました。たぶんあなたの誰かが私に、私が間違っていることを教えてくれるでしょう。

(MainActivityクラスを投稿する必要があるかどうかわかりません。)
ありがとうございます。:)

編集:これらすべての回答をありがとうございました。私が少し拡張しすぎていることを知っています。少し時間を取って試してみて、すべてのヒントを理解してください。ありがとうございます。

4

5 に答える 5

1

AsyncTask の実装には多くの概念的なエラーがあり、その理由や何がうまくいかないのかを突き止めることさえ非常に難しいため、AsyncTask の書き方に関するレシピとフィーリングのヒントをここに書きます。それらを適用し、それでもエラーが発生する場合は、もう一度尋ねます。

チップ:

  • AsyncTask 内に新しいスレッドを作成しないでください。doInBackground() はバックグラウンド スレッドで既に呼び出されています。
  • AsyncTask で runOnUiThread を呼び出さないでください。onPostExecute() は既に UI スレッドで呼び出されています。
  • アクティビティが一時停止する (onPause() が呼び出される) 場合は、AsyncTask で .pause() を呼び出します。NullPointerException
  • doInBackground()あなたが提案したように直接呼び出さないでください。execute()呼び出しは新しいスレッドを作成し、それを呼び出します(そのため、AsyncTask が必要です)
  • アクティビティ オブジェクトまたは AsyncTask へのコンテキストを保持するその他のものを保持しないでください。AsyncTask クラス宣言を Activity 自体の内部に配置するだけで、組織化のために、実際の処理で doInbackground() が別のクラスの 1 つのメソッドを呼び出すようにします。そうすれば、onPostExecute は UI を呼び出して更新できますが、データの収集/処理をアクティビティとは別に維持できます。

レシピ:

// put this class inside your Activity and
// just call a separate class (for organisation),
// or just put the code all in there (for no organisation)
private class SocketTask extends AsyncTask<Void, Void, String> {

@Override
protected String doInBackground(Void... params) {
    // Whatever you do inside here
    // DO NOT create a new thread!
    return APIConnection.callAPI();
}

@Override
protected void onPostExecute(String result) {
    if(result!=null){
    //Update your UI here
    }else{
    // Some error happen?
    }
}
}
于 2013-02-27T16:24:58.100 に答える
0

これは、スレッドで実行されるメソッドにある必要がありますが、MainActivityメソッドはそうではありません。doInBackground()onPostExecute()UIdoInBackground()

非同期タスク

4つのステップ

非同期タスクが実行されると、タスクは次の 4 つのステップを経ます。

タスクが実行される前に UI スレッドで呼び出される onPreExecute()。このステップは、通常、タスクをセットアップするために使用されます。たとえば、ユーザー インターフェイスに進行状況バーを表示します。

doInBackground(Params...) onPreExecute() が実行を終了した直後にバックグラウンド スレッドで呼び出されます。このステップは、時間がかかる可能性のあるバックグラウンド計算を実行するために使用されます。非同期タスクのパラメーターがこのステップに渡されます。計算の結果はこのステップで返される必要があり、最後のステップに戻されます。このステップでは、publishProgress(Progress...) を使用して、進行状況の 1 つ以上のユニットを公開することもできます。これらの値は、UI スレッドの onProgressUpdate(Progress...) ステップで発行されます。

onProgressUpdate(Progress...) は、publishProgress(Progress...) の呼び出し後に UI スレッドで呼び出されます。実行のタイミングは未定義です。このメソッドは、バックグラウンド計算がまだ実行されている間に、ユーザー インターフェイスに任意の形式の進行状況を表示するために使用されます。たとえば、進行状況バーをアニメーション化したり、テキスト フィールドにログを表示したりするために使用できます。

onPostExecute(Result) は、バックグラウンドの計算が終了した後に UI スレッドで呼び出されます。バックグラウンド計算の結果は、パラメーターとしてこのステップに渡されます。

于 2013-02-27T16:14:40.587 に答える
0

を使用してメイン スレッドで何かを実行しようとする代わりにAsynTask、メイン スレッド (つまり UI) で何かを実行する必要がある場合は、publishProgess()fromを呼び出しdoInBackground(...)、それが を呼び出しますonProgressUpdate(...)doInBackgroundを直接呼び出さないでくださいexecute()。. AsyncTaskdoInBackground()返さonPostExecute()れると、メイン スレッドで自動的に呼び出されます。

AndroidのドキュメントAsyncTaskは非常に優れており、適切な使用例があります。

于 2013-02-27T16:16:19.093 に答える
0

例外は、バックグラウンド スレッドでネットワーク操作を実行する必要があることを示しています。直接 doInBackground() を呼び出すと、呼び出しが行われたのと同じスレッドですべてが実行されるだけです。明らかに、メインのスレッドです。したがって、で新しいものを生成する必要がありますconnection.excute()。ただし、バックグラウンド スレッドから UI 要素を更新することはできません。メイン スレッドで実行するにonProgressUpdate()は、次のように AsyncTaskを実装する必要があります。

    @Override
    protected void onProgressUpdate(String... arg) {            
        main.addText(arg[0]);
    }

addText()ここで、 inのすべての呼び出しをdoInBackground()に置き換えますpublishProgress("whatever");。Async タスク宣言を に変更することを忘れないでくださいAsyncTask<Void, String, Void>。上記のすべてを完了すると、内部で別のスレッドを生成する必要はなくなりますdoInBackground()。とにかくバックグラウンド スレッドで実行されます。あなたの現在のコードはほぼ同じですが、これは混乱を解決し (これ以上はthrd = new Thread(new Runnable() {...ありませんmain.runOnUiThread...)、おそらく問題を解決します。

于 2013-02-27T16:18:01.390 に答える
0

マニフェストに必要なアクセス許可を追加しましたか?

<uses-permission android:name="android.permission.INTERNET"></uses-permission>
于 2013-02-27T16:07:50.563 に答える