我需要请求联系人的权限,当应用程序启动时我要求,在ViewModel部分我需要调用需要权限的方法。我需要检查权限是否由用户授予然后调用,但是对于检查权限,我需要访问Activity。而在我的ViewModel中,我没有对Activity的引用,也不想拥有,我怎么能克服这个问题呢?
答案 0 :(得分:1)
您可以创建一个PermissionRequester
类,使用LocalBroadcastManager
来请求具有自定义意图的权限。您的基本活动会解析此权限请求,并使用PermissionRequester
将结果发送回LocalBroadcastManager
。然后,您的ViewModel可以使用PermissionRequester.getInstance().requestPermission(permission)
,而无需与您的活动建立任何关联。这里是PermissionRequester.java
的示例代码:
public class PermissionRequester {
private static PermissionRequester instance;
public static synchronized PermissionRequester getInstance() {
instance = instance == null ? new PermissionRequester() : instance;
return instance;
}
private final Map<String, WeakReference<OnResultListener>> pendingListeners = new HashMap<>();
private PermissionRequester() {
LocalBroadcastManager.getInstance(MyApplication.getInstance()).registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent != null ? intent.getAction() : "";
if ("ACTION_PERMISSION_REQUEST_RESPONSE".equals(action)) {
callbackListener(intent.getStringExtra("LISTENER"), intent.getIntExtra("RESULT", -1));
}
}
}, new IntentFilter("ACTION_PERMISSION_REQUEST_RESPONSE"));
}
public void requestPermission(@NonNull OnResultListener listener, @NonNull String permission) {
pendingListeners.put(listener.getClass().getName() + listener.hashCode(), new WeakReference<>(listener));
Intent requestPermissionIntent = new Intent("ACTION_REQUEST_PERMISSION");
requestPermissionIntent.putExtra("PERMISSION", permission);
LocalBroadcastManager.getInstance(MyApplication.getInstance().getApplicationContext()).sendBroadcast(requestPermissionIntent);
}
private void callbackListener(String listener, int result) {
WeakReference<OnResultListener> listenerReference = pendingListeners.get(listener);
OnResultListener onResultListener = listenerReference != null ? listenerReference.get() : null;
if (onResultListener != null) {
pendingListeners.remove(listenerReference);
if (result == 1) {
onResultListener.onPermissionGranted();
} else if (result == 0) {
onResultListener.onPermissionDenied();
}
}
}
public interface OnResultListener {
void onPermissionGranted();
void onPermissionDenied();
}
}
在基本活动中接收自定义意图的代码类似于在PermissionRequester
构造函数中接收结果。但请注意在registerReceiver
和onResume
中unregisterReceiver
拨打onPause
。
答案 1 :(得分:1)
我刚遇到这个问题,我决定使用LiveData
代替。
核心概念:
ViewModel有一个关于需要提出权限请求的LiveData
ViewModel有一个方法(基本上是回调),如果授予了权限,则返回
SomeViewModel.kt
:
class SomeViewModel : ViewModel() {
val permissionRequest = MutableLiveData<String>()
fun onPermissionResult(permission: String, granted: Boolean) {
TODO("whatever you need to do")
}
}
FragmentOrActivity.kt
class FragmentOrActivity : FragmentOrActivity() {
private viewModel: SomeViewModel by lazy {
ViewModelProviders.of(this).get(SomeViewModel::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
......
viewModel.permissionRequest.observe(this, Observer { permission ->
TODO("ask for permission, and then call viewModel.onPermissionResult aftwewards")
})
......
}
}
答案 2 :(得分:0)
我做了这样的事情:
创建一个扩展AndroidViewModel的抽象类,该类使您可以访问应用程序上下文:
abstract class BaseViewModel(application: Application) : AndroidViewModel(application), CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onCleared() {
super.onCleared()
job.cancel()
}
}
现在,通过扩展BaseViewModel类来创建视图模型,您将可以访问应用程序上下文
class AdminViewModel(application: Application) : BaseViewModel(application) {
.....
}
现在,您始终可以访问可以用于访问资源的上下文。