V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
codechaser
V2EX  ›  Android

请教一个关于 android 静态变量的问题

  •  
  •   codechaser · 2019-01-09 17:36:15 +08:00 · 8983 次点击
    这是一个创建于 2143 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有一个类,里面存储着一些 static 的变量,在整个程序中这些变量的值会变化,类似于这样:

    class Foo {
    	public static int FOO = 0;
    }
    

    这个 FOO 类里的变量 FOO 我会在 Service 里读取他,但是同时也有可能会被一些 activity 里的回调函数修改。service 有时候不能实时读取这个被修改的值,我现在的实现就是这样,让这个类可以被所有人访问修改,谁要用这个数值谁就去读,但是就像刚才说的,也许我想要的值会在我读取之后才被修改,造成了滞后。请问应该怎么解决呢?还是我这样的用法时大错特错的。

    21 条回复    2019-01-13 11:15:11 +08:00
    11wangyaoda
        1
    11wangyaoda  
       2019-01-09 20:13:43 +08:00
    关键词。atomic volatile concurrency.
    ho121
        2
    ho121  
       2019-01-09 20:17:27 +08:00 via Android
    可能 service 和 activity 没有在一个进程中
    codechaser
        3
    codechaser  
    OP
       2019-01-09 20:22:09 +08:00 via Android
    @11wangyaoda 你好, 这个好像和原子性没啥关系吧?我这个变量在整个应用运行过程中都有可能被修改。
    codechaser
        4
    codechaser  
    OP
       2019-01-09 20:23:28 +08:00 via Android
    @ho121 service 和 activity 都是同一个应用
    guotao2beijing
        5
    guotao2beijing  
       2019-01-09 20:36:28 +08:00
    应该不是滞后,你可以修改 F00 的值以后直接打印出来看看有没有修改。
    猜测是 service 在启动的时候就把 F00 的值持有在栈内存里了,而你改 F00 的值是改动堆内存里的数据,service 不知道。
    symeonchen
        6
    symeonchen  
       2019-01-09 20:37:22 +08:00 via Android
    取决于你的具体场景,不谈多进程的前提下,数据能被各处获取->单例 /持久化 /etc.;数据被操作的一段时间内禁止修改->加锁;数据的变化实时同步到各处->回调 /通知
    kx5d62Jn1J9MjoXP
        7
    kx5d62Jn1J9MjoXP  
       2019-01-09 20:38:07 +08:00 via Android
    使用观察者模式:
    对于需要接收最新值的 service,subscribe 一下
    每次对这个值进行改动的时候,通知所有的 subscriber
    Icezers
        8
    Icezers  
       2019-01-09 20:39:48 +08:00 via iPhone
    @codechaser 同一个应用不一定是同一个进程
    frienmo
        9
    frienmo  
       2019-01-09 23:36:04 +08:00
    @Icezers 不好意思杠一下,应该是线程 thread 吧。同一个 app(jvm)了,一定是同一个进程 process 吧。
    crayygy
        10
    crayygy  
       2019-01-09 23:40:48 +08:00 via iPhone
    @frienmo 不一定的,进程可以有多个,取决于实现,只是一般进程通信没有线程那么方便所以这么用的不多。
    rosu
        11
    rosu  
       2019-01-09 23:51:38 +08:00 via Android
    对值的读写顺序,应该只能通过程序逻辑来保证了。

    在语法方面应该不存在先修改,并且可多次修改后再读取。

    1. 要么像楼上那样,把这个变量用一个订阅改写成可订阅式,当被修改就通知订阅者( Service ),后者用标志变量来确认该值的修改状态?但是这样也不十分符合你的需求。也需要程序逻辑来保证。

    2. 如果是一次修改,之后不再对该变量执行写操作,可以用 kotlin 里的 by...lazy 来延迟初始化。
    wolegequ
        12
    wolegequ  
       2019-01-10 00:42:44 +08:00 via Android
    修改的时候打日志。btw 是通过 setter 修改的吗?
    codechaser
        13
    codechaser  
    OP
       2019-01-10 08:31:47 +08:00 via Android
    @guotao2beijing 静态变量不是一直存在静态存储区吗?就是说我每次都得主动更新值是吗
    ho121
        14
    ho121  
       2019-01-10 09:13:56 +08:00 via Android
    @codechaser 简单的场景,service 改了值,然后进程被杀掉了,你再打开 activity,static 变量又被重新初始化一遍
    codechaser
        15
    codechaser  
    OP
       2019-01-10 09:19:42 +08:00 via Android
    @ho121 是这样的,所以我现在只考虑应用运行过程中就行了😂
    stuazt
        16
    stuazt  
       2019-01-10 10:18:47 +08:00
    LiveData/MutableLiveData 了解一下,官方 Android Architecture Components 的一个库。
    brucewuio
        17
    brucewuio  
       2019-01-10 14:06:32 +08:00
    重新学 java
    codechaser
        18
    codechaser  
    OP
       2019-01-10 15:40:54 +08:00 via Android
    @brucewuio 学哪个部分?我马上去看
    siyehua
        19
    siyehua  
       2019-01-10 22:31:41 +08:00
    @codechaser
    首先哪怕是同一个应用,也可以是不同的进程。
    其次,楼主表达的非常不清晰:到底是要每次去读 /写的时候,取的值一定是最新的,还是怎么样,从楼主题目上说的不是很清楚。
    然后,就算整个应用都可以访问,也可以做成私有的,然后使用方法来 get/set,这样无论是添加监听,或者是添加同步方法,都要容易得多。
    最后,如果这个变量有比较多的地方用到,且涉及到多线程 /进程,而且变化比较复杂。比如说这个值的写入,必须依赖其他地方的值(楼主说的滞后问题),那我建议使用同步方法修饰 set/get。如果写入不需要依赖,则可以使用 volatile
    nicevar
        20
    nicevar  
       2019-01-13 11:12:53 +08:00
    @frienmo 同一个应用不一定是同一个进程,你在 service 的 process 属性里面配置 remote 就是在不同的进程了。这种情况是不能通过静态变量共享的。
    楼主的表达不够清晰,不过你的想法也是有点问题,你这种情形为什么不用 android 的 SharePreference 呢?很多人在使用静态变量的时候会犯两个错误,一个是不初始化,另一个就是跨进程访问。
    codechaser
        21
    codechaser  
    OP
       2019-01-13 11:15:11 +08:00 via Android
    @nicevar 那些变量是随时要用的,所以我没考虑用 sharedpreference
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5273 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 08:46 · PVG 16:46 · LAX 00:46 · JFK 03:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.