GVKun编程网logo

即使在另一个线程上调用subscribeOn(),也可以在主线程上运行

23

如果您想了解即使在另一个线程上调用subscribeOn和,也可以在主线程上运行的知识,那么本篇文章将是您的不二之选。我们将深入剖析即使在另一个线程上调用subscribeOn的各个方面,并为您解答,

如果您想了解即使在另一个线程上调用subscribeOn,也可以在主线程上运行的知识,那么本篇文章将是您的不二之选。我们将深入剖析即使在另一个线程上调用subscribeOn的各个方面,并为您解答,也可以在主线程上运行的疑在这篇文章中,我们将为您介绍即使在另一个线程上调用subscribeOn的相关知识,同时也会详细的解释,也可以在主线程上运行的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

即使在另一个线程上调用subscribeOn(),也可以在主线程上运行

即使在另一个线程上调用subscribeOn(),也可以在主线程上运行

我的一项活动遇到了一个奇怪的问题。从拍照/录像回来时,onActivityResult我正在显示一个对话框,允许用户命名相机。用户按下“确定”后,我将onNext()使用所请求的文件名发送给主题,该主题将复制文件(并显示进度对话框)。

由于某种原因map(),即使我调用,总是在主线程上调用执行复制的函数subscribeOn(Schedulers.io())

@Overrideprotected void onActivityResult(final int requestCode, int resultCode, Intent intent) {    ...    final PublishSubject<String> subject = PublishSubject.create();`    mSubscription = subject            .subscribeOn(Schedulers.io())            .map(new Func1<String, String>() {                @Override                public String call(String fileName) {                    Log.I.d(TAG,"map");                    return doSomeIOHeavyFuncition();                }            })            .observeOn(AndroidSchedulers.mainThread())            .subscribe(new Action1<String>() {                @Override                public void call(final String fullPath) {                    Log.d(TAG,"onNext");                    doSomethingOnUI(fullPath);                    subject.onCompleted();                }            }, new Action1<Throwable>() {                @Override                public void call(Throwable throwable) {                    ...                }            }, new Action0() {                @Override                public void call() {                    ...                }            });    final AlertDialog dialog = new AlertDialog.Builder    ....    .create()            .show();    dialog.getButton(DialogInterface.BUTTON_POSITIVE)            .setOnClickListener(new View.OnClickListener() {                @Override                public void onClick(View view) {                    String someString = getStringFromDialog(dialog);                    dialog.dismiss();                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);                    imm.hideSoftInputFromWindow(input.getWindowToken(), 0);                    showProgressDialog();                    subject.onNext(someString);                }            });}

更改subscribeOn(Schedulers.io())呼叫以observeOn(Schedulers.io())解决问题。我还是想知道为什么它不起作用…

答案1

小编典典

subscribeOn并且observeOn是那里最混乱的运营商。前者确保订阅副作用在指定的调度程序(线程)上发生,但这并不意味着值也将在该线程上弹出。

例如,如果您的观察者在订阅时打开了一个网络连接,则您不希望该链接在主线程上运行,因此,您需要subscriptionOn来指定该订阅的位置,从而创建网络连接。

当数据最终到达时,发出线程可以是任何东西,调度程序之一或后台普通旧线程。由于我们不知道或不喜欢该线程,因此我们希望将对数据的观察移到另一个线程。这是observeOn的作用:确保操作符之后的操作符将在指定的调度程序上执行其onNext逻辑。Android开发人员已经使用它来将对值的观察移回主线程。

但是很少解释的是,当您希望在最终结果再次落入主线程之前又需要在主线程上进行一些额外的计算时会发生什么:使用多个observeOn运算符:

source.observeOn(Schedulers.computation()).map(v -> heavyCalculation(v)).observeOn(Schedulers.io()).doOnNext(v -> { saveToDB(v); }).observeOn(AndroidSchedulers.mainThread())...

Android JNI功能在主线程上运行?

Android JNI功能在主线程上运行?

我对来自 Android的JNI函数调用有疑问.他们的运行方式与Android应用程序相同吗?如果本机功能花费更多时间运行,UI会冻结吗?

解决方法

JNI调用与任何其他Java调用同步,您可以切换或生成线程,但如果未指定它,则它们将在同一线程上执行.所以如果从UI线程调用JNI函数,它将被阻塞,直到函数返回.

android – AsyncTask onPostExecute没有在主线程上运行?

android – AsyncTask onPostExecute没有在主线程上运行?

我的应用程序上有一些活动可以访问网络服务.由于我不想占用主线程,因此该代码位于AsyncTask中.但是,我不希望用户在调用Web服务时操作Activity,因此在执行AsyncTask之前,我会显示一个旋转并阻塞屏幕的ProgressDialog.在AsyncTask的onPostExecute方法中,我要做的第一件事就是关闭ProgressDialog.

这应该可以防止用户在没有实际阻塞主线程的情况下操作Activity.

但是,我注意到有几次ProgressDialog从未被解雇,用户卡住了. AsyncTask已完成,onPostExcute已执行,但仍显示ProgressDialog. ProgressDialog没有机会被解雇,用户被卡在屏幕上.他们唯一的选择是访问Android设置应用并强制停止我的应用程序.

有谁知道为什么会这样?我该怎么办才能修复它?

相关代码:

这是我展示ProgressDialog并启动任务的方式:

mProgress = ProgressDialog.show(this,"","Syncing...",true);
(new MyAsyncTask()).execute(intUserId);

这是该任务的onPostExcute.没有“@Override”

protected void onPostExecute(Boolean result) {
        if (mProgress != null) {
            mProgress.dismiss();
            mProgress = null;
        }
    }

解决方法

检查一下:

>确保在UI线程上调用了asynctack.execute().>在onPostExcute()上使用@Override以确保它已正确定义.

android – 如何在主线程上运行服务?

android – 如何在主线程上运行服务?

我正在尝试启动服务,然后打开套接字与服务器连接.

在按钮上单击我创建新线程然后启动服务.

Thread t = new Thread(){
        public void run(){
            mIntent= new Intent(MainActivity.this,ConnectonService.class);
            mIntent.putExtra("KEY1","Value used by the service");
            context.startService(mIntent);
        }
    };
t.start();

然后在服务上,我尝试打开套接字并与服务器连接

@Override
public int onStartCommand(Intent intent,int flags,int startId) {
    //Todo do something useful


    try {
        InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
        socket = new Socket(serverAddr,SERVERPORT);
        Scanner scanner = new Scanner(socket.getInputStream());
        message = scanner.nextLine();
    } catch (IOException e) {
        e.printstacktrace();
    }

    return Service.START_NOT_STICKY;
}

但是当我打电话给我时,我有错误

08-30 08:56:49.268: E/AndroidRuntime(3751): java.lang.RuntimeException: Unable to start service com.example.testofconnection.ConnectonService@40ef02a8 with Intent { cmp=com.example.testofconnection/.ConnectonService (has extras) }: android.os.networkonmainthreadException*

我认为问题是服务在主线程上,但是我找不到如何在新的(独立)线程上启动服务以保持连接活动?

解决方法

您可以使用IntentService.只需使用主线程中的Intent正常启动它. onHandleIntent()方法在后台线程中执行.把你的套接字代码放在那里.这是一个示例代码.
public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // this method is called in background thread
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

在您的活动中,您将按以下方式启动服务.

startService(new Intent(this,MyIntentService.class));

如果您需要持久的服务,您可以创建一个正常的服务并在那里启动一个线程.这是一个例子.确保将其作为“前台”服务启动.这将使服务运行更长时间而不会被Android杀死.

public class MyAsyncService extends Service {

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while(true) {
                // put your socket-code here
                ...
            }
        }
    }

    @Override
    public void onCreate() {

        // start new thread and you your work there
        new Thread(runnable).start();

        // prepare a notification for user and start service foreground
        Notification notification = ...
        // this will ensure your service won't be killed by Android
        startForeground(R.id.notification,notification);
    }
}

android – 广播接收器在主线程上运行?

android – 广播接收器在主线程上运行?

我在我的应用程序中使用MQTT服务器.所以我将数据作为单个字符串而不是批量json数据.因此,如果有100条记录,我的广播接收机的onReceive将被调用100次.我从接收到的字符串中提取数据并仅将其保存到此接收器类中的DB.我知道通常广播接收器太阳在主线程.所以我的应用程序将挂起,如果我遵循这种方法.那么适合的方法是什么呢?如果我想在单独的线程中运行我的接收器,我该怎么办?

这是我注册我的接收器的方式:

mMessageReceiver = new MQTTMessageReceiver();
IntentFilter intentFilter = new IntentFilter(MQTTService.MQTT_MSG_RECEIVED_INTENT);
registerReceiver(mMessageReceiver,intentFilter);

解决方法

所以我可以建议以下解决方案:

>不要在BoradcastReceiver中进行繁重的处理(但似乎
它不是一个选项)
>开始新的Thread或
AsyncTask或装载机,或任何线程机制
喜欢用.所以这将把计算密集的部分转移到
单独的线程,不阻止UI.
>正如axierjhtjz建议你的那样
可以运行IntentService(因为它创建了一个单独的工作
线程)与MQTTMessageReceiver(我假设这是你的
broadcastReceiver的子类,它将处理数据并通知UI
穿过另一个broadcastReceiver.

我个人建议使用第三种方式,因为它使您的应用程序更加模块化,这意味着更容易支持和扩展程序

编辑:我也考虑过第四种方式:

>您可以使用this method注册Receiver,提供一个Handler对象,用于标识将进行数据处理的Thread.

关于即使在另一个线程上调用subscribeOn,也可以在主线程上运行的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Android JNI功能在主线程上运行?、android – AsyncTask onPostExecute没有在主线程上运行?、android – 如何在主线程上运行服务?、android – 广播接收器在主线程上运行?等相关知识的信息别忘了在本站进行查找喔。

本文标签: