正在从 BroadcastReceiver 获取方法以更新 UI

Fetching methods from BroadcastReceiver to update UI

我正在尝试根据 BroadcastReceiver 中变量的变化来更新 UI。因此,我需要调用 class 的方法(以获取我提到的变量),它在 MainActivity 中扩展 BroadcastReceiver 取决于但我无法获得真正的 return 值无论如何。

扩展BroadcastReceiver的class是这样的:

public class ProviderChangeReceiver extends BroadcastReceiver {

    private static boolean isProviderActive;
    @Override
    public void onReceive(Context context, Intent intent) {
        LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
            Log.v("-> ", "GPS + NETWORK");
            isProviderActive = true;
        }

        else if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && !lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
            Log.v("-> ", "GPS");
            isProviderActive = true;
        }

        else if (lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) && !lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Log.v("-> ", "NETWORK");
            isProviderActive = true;
        }

        else
        {
            Log.v("-> ", "DISCONNECT");
            isProviderActive = false;
        }
    }

    public static boolean isProviderActive(){
        return isProviderActive;
    }
}

我需要获取 isProviderActive 的真实值以用于 MainActivity 的这一部分:

...
private class ProviderChangeReceiver_updateUI extends ProviderChangeReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        MapsActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.v("-A", ""+ isProviderActive());
                if (isProviderActive())
                    originButton.setVisibility(View.VISIBLE);
                else
                    originButton.setVisibility(View.INVISIBLE);
            }
        });
    }
}

我知道将 isProviderActive 指示为静态不是一个好方法,但我只是想观察它的变化。如您所料,我一直得到无意义的 return 值。对于 boolean isProviderActive 的值没有问题,您有什么建议?

编辑:我根据 BroadcastReceiver 中的变化更新 UI 的临时解决方案。

忘记为 ProviderChangeReceiver 创建一个单独的 class。应在 MainActivity 中添加以下代码段,而不是上面的代码段。另外,不言而喻,onCreate().

中有ProviderChangeReceiver的初始化
...
private class ProviderChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        MapsActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Log.v("COUNT: ", "" + count++);
                if (isLocationProviderActive()) {
                    originButton.getBackground().setAlpha(220);
                    originButton.setEnabled(true);
                    //marker.setVisible(true);
                }
                else {
                    originButton.getBackground().setAlpha(77);
                    originButton.setEnabled(false);
                    marker.setVisible(false);
                }
            }
        });
    }
}

private boolean isLocationProviderActive(){
    if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
        return true;
    return false;
}

当然也可以在onCreate()中注册接收者:

registerReceiver(pcr, new IntentFilter("android.location.PROVIDERS_CHANGED"));

每次 isProvidrActive 更改整个 activity 重新生成的原因是因为我使用 context.startActivity(i) 发送了意图,但这次我们使用 [=15= 发送了意图] 到 ProviderChangeReceiver_updateUI 内部 class,它只更新 UI 的所需部分。下面是新代码。

private static boolean isProviderActive;
@Override
public void onReceive(Context context, Intent intent) {
    LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
        Log.v("-> ", "GPS + NETWORK");
        isProviderActive = true;
    }

    else if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && !lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
        Log.v("-> ", "GPS");
        isProviderActive = true;
    }

    else if (lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) && !lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        Log.v("-> ", "NETWORK");
        isProviderActive = true;
    }

    else
    {
        Log.v("-> ", "DISCONNECT");
        isProviderActive = false;
    }

    //Send value of isProviderActive to ProviderChangeReceiver_updateUI
    Intent i = new Intent(context, ProviderChangeReceiver_updateUI.class);
    i.putExtra("isProvidrActv", isProviderActive);
    i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.sendBroadcast(i);
}

编辑您的清单文件以启用内部 class ProviderChangeReceiver_updateUI 来侦听我们的 broadcastReciever 发送的广播,将以下条目添加到清单

<receiver  android:name="<package-name>.MainActivity$ProviderChangeReceiver_updateUI"
            android:enabled="true" >
            <intent-filter>
            </intent-filter>
        </receiver>

$ 符号表示内部 class。除非需要,否则无需添加 intent-filters

并且在你的ProviderChangeReceiver_updateUIclass中的onReceive()方法中得到isProviderActive

的值
...
//changed the identifiers from private to public static and the class extends //BroadcastReceiver
public static class ProviderChangeReceiver_updateUI extends BroadcastReceiver {

    //Empty constructor to prevent exception can't instantiate no empty constructor
    public ProviderChangeReceiver_updateUI(){

    }

    //Removed the final keyword from handler
    private Handler handler; // Handler used to execute code on the UI thread

    public ProviderChangeReceiver_updateUI(Handler handler) {
        this.handler = handler;
    }

    @Override
    public void onReceive(final Context context, final Intent intent) {
        boolean isProvidrActv = intent.getBooleanExtra("isProvidrActv", false);
        //mapsActivity is a global static object of the class MapsActivity<br/>
        //instantiate it the onCreate() method of mainactivity for ex:<br/>
/*public class MapsActivity extends Activity{<br/>
         static MapsActivity mapsActivity;

         @Override
         protected void onCreate(Bundle savedInstancestate){
        ma  = new MapsActivity();
        }*/
        mapsActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (isProvidrActv)
                    originButton.setVisibility(View.VISIBLE);
                else
                    originButton.setVisibility(View.INVISIBLE);
            }
        });
    }
}

我认为处理此类事情的一个好方法是使用事件总线。

看看 Squares Otto 库。

在您的广播接收器中,您将发布更改事件,然后在您的 activity 中,您将订阅该事件并更新 ui。

根据你问题的上下文,我认为你可以完全避免广播接收器,因为我怀疑你有东西在监视你的提供者然后广播事件。

更新:(基于评论)

我认为它的工作方式应该是这样的

在检测位置提供商变化的代码中:

if (bothProvidersAreStopped()) {
   bus.publish(new BothProvidersStoppedEvent());
} else if (onlyNetworkProviderIsStopped() {
   bus.publish(new NetworkProviderStoppedEvent());
} else if (onlyGpsProviderIsStopped() {
   bus.publish(new GpsProviderStoppedEvent());
}

在你的 activity

@Subscribe public void onBothProvidersStopped(BothProvidersStopped event) {
    // handle case were both providers just stopped
}

@Subscribe public void onNetworkProvidersStopped(BothProvidersStopped event) {
    // handle case were network provider just stopped
}

@Subscribe public void onGpsProvidersStopped(BothProvidersStopped event) {
    // handle case were gps provider just stopped
}