runOnUiThread从服务到活动

时间:2016-06-04 19:35:51

标签: android android-service

我有一个方法“send()”,它将值发送到服务器,然后从服务器获得响应0或1。然后我想激活一个方法,检查它的0或1,然后我想激活一个从服务调用MainActivity的方法。

这是服务代码

    public class SendThreadCommunication extends Thread {
private final static String TAG = "SendThreadCommunication";
private final int READ_TIMEOUT = 100000;
private final int CONNECTION_TINEOUT = 100000;
private Looper myLooper;
private int mResponseCode;
private String mData = "";

private final ServerRequest req;
// private RegisterUser user;
private static String ans;

public SendThreadCommunication(ServerRequest req) {

    this.req = req;
}

public String readWebData(InputStream stream) {

    String line = "";
    StringBuffer buffer = new StringBuffer();
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

    try {
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }
        reader.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block

    }
    return buffer.toString();

}

@Override
public void run() {
    try {
        send();
       // evaluateDataAndRespondToFragment(mData);
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}


public void send() throws ClientProtocolException, IOException {
    OutputStream mOutputStream = null;
    BufferedWriter mWriter = null;

    List<NameValuePair> mParameters = req.getParameters();

    URL url = null;
    HttpURLConnection connection = null;
    try {
        Looper.prepare();
        url = new URL(req.returnRequestUrl());
        connection = (HttpURLConnection) url.openConnection();
        connection.setReadTimeout(READ_TIMEOUT);
        connection.setConnectTimeout(CONNECTION_TINEOUT);
        connection.setRequestMethod(Params.HTTP_REQUEST_METHOD_POST);
        connection.setDoOutput(true);
        connection.setDoInput(true);
        mOutputStream = connection.getOutputStream();
        mWriter = new BufferedWriter(new OutputStreamWriter(mOutputStream, Params.UTF8));
        String sparams = URLEncodedUtils.format(mParameters, Params.UTF8);
        mWriter.write(sparams);
        mWriter.flush();

        mResponseCode = connection.getResponseCode();
        if (mResponseCode > 203) {
            mData = readWebData(connection.getErrorStream());
            //this.req.getResponse().notGoodServerEroorr();
        } else {
            mData = readWebData(connection.getInputStream());

        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        if (connection != null) {
            try {
                if (mOutputStream != null)
                    mOutputStream.close();
                if (mWriter != null)
                    mWriter.close();

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            connection.disconnect();
            evaluateDataAndRespondToFragment(mData);
            myLooper = Looper.myLooper();
            Looper.loop();
            myLooper.quit();

        }
    }
  }

private void evaluateDataAndRespondToFragment(String mData) {
    Listen lis = this.req.getResponse();

    if (mData.equals("1"))
        lis.good();
    else
        lis.notGood();

     if (mData.equals("0"))
     {
         lis.userGcmNotRegistered();
     }
    }
 }

此服务代码发送到服务器的值并获得响应。方法“evaluateDataAndRespondToFragment”检查其是0还是1,然后激活相应的方法。该方法应该触发MainActivity中的其他方法。 我知道 runOnUiThread 处理这个,但我不知道如何使用它。 MainActivity上的方法更改了UI。

这是MainActivity代码

  public class MainActivity extends Activity implements SensorEventListener, Listen {

private BroadcastReceiver statusReceiver;
private IntentFilter mIntent;
Sensor accelerometer;
SensorManager sm;
TextView acceleration;
SendValues sv;
int counter3 = 0;
int counter5 = 0;
int pastTime = 0;

private static final String TAG = "MainActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    }


@Override
public void good() {
    Toast.makeText(getApplication(), "successful transfer", Toast.LENGTH_LONG).show();
}

@Override
public void notGood() {
    Toast.makeText(getApplication(), "UNsuccssful transfer", Toast.LENGTH_LONG).show();
}

@Override
public void userGcmNotRegistered() {
    Toast.makeText(getApplication(), "There is some problem, please register again to the App", Toast.LENGTH_LONG).show();
  }

}

这里它应该激活其中一种方法“好”,“不好”.... 我知道 runOnUiThread 处理它,但我不知道如何使用它和在哪里。 如果有人能告诉我该怎么做,我会很感激。

2 个答案:

答案 0 :(得分:1)

服务没有 runOnUiThread 方法,但您可以使用意图代替。

简单地说,

  1. 为您的活动添加 BroadcastReceiver
  2. 将接收器添加到 AndroidManifest.xml
  3. 从您的服务中发送意图
  4. <强> MainActivity.java

    public class MainActivity extends Activity implements SensorEventListener, Listen {
    
        private BroadcastReceiver statusReceiver;
        private IntentFilter mIntent;
        Sensor accelerometer;
        SensorManager sm;
        TextView acceleration;
        SendValues sv;
        int counter3 = 0;
        int counter5 = 0;
        int pastTime = 0;
    
        private static final String TAG = "MainActivity";
    
        statusReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    switch(intent.getIntExtra("status", -1) {
                        case 1:
                            good();
                            break;
                        case 2:
                            notGood();
                            break;
                        default:
                            userGcmNotRegistered();
                    }
                }
            };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            registerReceiver(statusReceiver, new IntentFilter("com.yourpackage.yourapp.GET_STATUS_INTENT");
            }
    
    
        @Override
        public void good() {
            Toast.makeText(getApplication(), "successful transfer", Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void notGood() {
            Toast.makeText(getApplication(), "UNsuccssful transfer", Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void userGcmNotRegistered() {
            Toast.makeText(getApplication(), "There is some problem, please register again to the App", Toast.LENGTH_LONG).show();
          }
    
        }
    

    一个简单的 AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.yourpackage.yourapp"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="19"
            android:targetSdkVersion="19" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.yourpackage.yourapp.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
            <receiver android:name="MainActivity">
                    <intent-filter>
                            <action android:name="com.yourpackage.yourapp.GET_STATUS_INTENT">
                            </action>
                    </intent-filter>
         </receiver>
        </application>
    </manifest>
    

    evaluateDataAndRespondToFragment 方法

    private void evaluateDataAndRespondToFragment(String mData) {
    
        Intent intent = new Intent("com.yourpackage.yourapp.GET_STATUS_INTENT");
        intent.putExtra(status, mData);
        sendBroadcast(intent);
    
        }
     }
    

    此外,您需要在活动的onResume / onPause方法中注册/取消注册。

答案 1 :(得分:0)

有点关闭主题;但是,Beremaran的答案是正确的,你无法从服务中获得主线程。但是,runOnUiThread是一个非常重要的知识和使用概念,以避免阻塞主线程。阻止主线程将导致系统终止您的应用。

假设你有一些网络任务要做,你知道这可能需要一些时间。因此,你开始一个新的线程来做慢工作。

new Thread(new Runnable() {
    @Override
    public void run() {
       messageFromSlowStuff = doSomeSlowStuff();
    };
}).start();

现在您可能希望使用新数据 messageFromSlowStuff 填充UI,但您不能,因为它只是来自主线程。

getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        myTextView.setText(messageFromSlowStuff)
    }
});

如果您只是按照上面的示例更新视图,则可以使用View.post()替代runOnUiThread。

myTextView.post(new Runnable() {
    public void run() {
        messageFromSlowStuff = doSomeSlowStuff();
        myTextView.setText(messageFromSlowStuff);
    }
});

以下是有关View.post()的文档:"post reference"