I have been using a network check functionality in-app, but all things are available in Kotlin now the same thing wants to integrate in java facing some issue related to lazy calling.
This is how I can check network state in Kotlin
class MainActivity : AppCompatActivity(), ConnectivityStateListener {
private lateinit var tv: TextView
private val provider: ConnectivityProvider by lazy { ConnectivityProvider.createProvider(this) }
#RequiresApi(Build.VERSION_CODES.M)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv = findViewById(R.id.connectivity_state)
val button = findViewById<View>(R.id.button)
val currentState = findViewById<TextView>(R.id.current_state)
button.setOnClickListener {
val hasInternet = provider.getNetworkState().hasInternet()
currentState.text = "Connectivity (synchronously): $hasInternet"
}
}
override fun onStart() {
super.onStart()
provider.addListener(this)
}
override fun onStop() {
super.onStop()
provider.removeListener(this)
}
override fun onStateChange(state: NetworkState) {
val hasInternet = state.hasInternet()
tv.text = "Connectivity (via callback): $hasInternet"
}
private fun NetworkState.hasInternet(): Boolean {
return (this as? ConnectedState)?.hasInternet == true
}
}
this is how I integrated into Java
#Override
protected void onStart() {
super.onStart();
provider=ConnectivityProvider.createProvider(this);
provider.addListener(this);
}
#Override
protected void onStop() {
super.onStop();
provider.removeListener(this);
}
#Override
public void onStateChange(#NotNull ConnectivityProvider.NetworkState state) {
Log.d("To ConnectivityProvider-----", state.toString());
Toast.makeText(LoginActivity.this, "Available", Toast.LENGTH_SHORT).show();
if( hasInternet(state)){
Toast.makeText(LoginActivity.this, "Available", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(LoginActivity.this, "No Internet", Toast.LENGTH_SHORT).show();
}
}
private boolean hasInternet(#NotNull ConnectivityProvider.NetworkState state) {
ConnectivityProvider.NetworkState.ConnectedState var2 = (ConnectivityProvider.NetworkState.ConnectedState)state;
if (var2.getHasInternet()) {
return true;
}
return false;
}
java.lang.ClassCastException:
com.ro.other.connectivity.base.ConnectivityProvider$NetworkState$NotConnectedState
cannot be cast to
com.ro.other.connectivity.base.ConnectivityProvider$NetworkState$ConnectedState
gitlink help me to integrate this in java
The problem here is with type casting, not with lazy calling. The behaviour of the hasInternet methods in the given Kotlin and Java code is different.
Kotlin:
return (this as? ConnectedState)?.hasInternet == true
If the current NetworkState is not a ConnectedState, the typecast this as? ConnectedState will return null, and the method will return false.
Java:
ConnectivityProvider.NetworkState.ConnectedState var2 = (ConnectivityProvider.NetworkState.ConnectedState)state;
if (var2.getHasInternet()) {
return true;
}
return false;
This code assumes that state is a ConnectedState (instead of checking it), and throws a ClassCastException if it is an instance of a different class.
The correct Java code for hasInternet method would be:
if (!(state instanceof ConnectivityProvider.NetworkState.ConnectedState)) {
return false;
}
ConnectivityProvider.NetworkState.ConnectedState var2 = (ConnectivityProvider.NetworkState.ConnectedState)state;
if (var2.getHasInternet()) {
return true;
}
return false;
Related
I have list from API that show data class as follow:
data class Ibadah(
val ibadahText: String,
val id: Int,
val isComplete: Boolean,
val journalId: Int,
val userId: String
)
and this class:
#Singleton
class IbadahRVAdapter #Inject constructor(#ApplicationContext val context: Context) :
RecyclerView.Adapter<IbadahRVAdapter.IbadahViewHolder>() {
lateinit var ibadahslist: List<Ibadah>
#Named("journal_url")
#Inject
lateinit var journalInterface: JournalInterface
lateinit var ibadahs_isCompleted: ArrayList<Boolean>
lateinit var ibadahList: ArrayList<Ibadah>
private lateinit var recyclerView: RecyclerView
var jId = 0
inner class IbadahViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IbadahViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.ibadah_rv_item, parent, false)
return IbadahViewHolder(view)
}
override fun getItemCount(): Int {
return ibadahslist.size
}
fun setQuranSurahList(quransurahlist: List<Ibadah>) {
this.ibadahslist = quransurahlist;
notifyDataSetChanged()
}
override fun onBindViewHolder(holder: IbadahViewHolder, position: Int) {
ibadahs_isCompleted = ArrayList()
holder.itemView.apply {
ibadah_item_text.setText(ibadahslist[position].ibadahText)
ibadah_item_chechbox.setChecked(ibadahslist[position].isComplete)
ibadah_item_chechbox.setOnCheckedChangeListener { checkBox, isChecked ->
patchIbadah(position)
if (!ibadahs_isCompleted.contains(false)) {
AlertDialog.Builder(context)
.setCancelable(true)
.setView(R.layout.finish_ibadh)
.show()
} else {
}
}
}
}
fun patchIbadah(position: Int) {
getToken()
journalInterface.patchIbadah(ibadahslist[position].id, token)
.enqueue(object : Callback<ResponseBody> {
override fun onResponse(
call: Call<ResponseBody>,
response: Response<ResponseBody>
) {
if (!response.isSuccessful) {
getIbadahsList()
Log.e(this.toString(), "code: " + response.code())
}
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
Log.e(this.toString(), "error: " + t.message)
}
})
}
fun setupRV() {
this.setQuranSurahList(ibadahList)
recyclerView.layoutManager = LinearLayoutManager(this.context)
recyclerView.adapter = this
}
fun getIbadahsList() {
ibadahList = ArrayList()
journalInterface.getIbadahs(jId, token).enqueue(object : Callback<List<Ibadah>> {
override fun onResponse(
call: Call<List<Ibadah>>,
response: Response<List<Ibadah>>
) {
if (response.isSuccessful) {
response.body()?.forEach {
ibadahList.add(
Ibadah(
it.ibadahText, it.id, it.isComplete, it.journalId, it.userId
)
)
ibadahs_isCompleted.add(it.isComplete)
}
setupRV()
} else {
}
}
override fun onFailure(call: Call<List<Ibadah>>, t: Throwable) {
}
})
}
}
to show list like this:
My current code show the AlertDialog, if I check or uncheck any item.
AlertDialog is placed in onBindViewHolder.
I want the AlertDialog to appear only if all items are checked and if any item of the list not checked, do not appear.
What am I doing wrong here?
You shouldn't be showing AlertDialog inside the adapter. use listener to update your changes in Fragment/Activity.
Solution for your question: Assign new/another list in Fragment/Activity whatever the changes are made just pass through the listener and add those changes to the new list, then validate that the original list size equals to new list size. If the condition is true then show AlertDialog.
Hi everyone I have the following problem when I run my project on Intellij everything works fine but when i make the build using maven install and run my project appears this issue.
[Failed to evaluate expression 'isAuthenticated()
&& isPermitted('domain:read:*')'][1]
[1]: https://i.stack.imgur.com/LkaY6.png
my code
#PreAuthorize("isAuthenticated() && isPermitted('domain:read:*')")
#GetMapping(produces = [(MediaType.APPLICATION_JSON_VALUE)])
fun search(query: DomainQuery): ResponseEntity<ArpiaPage<DomainOutput>> {
val retval = service.search(query)
return ResponseEntity(
retval.map { domain -> converter.convert(domain, DomainOutput::class.java) },
HttpStatus.OK
)
}
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled=true)
class ShiroMethoSecurityConfig : GlobalMethodSecurityConfiguration() {
override fun createExpressionHandler(): MethodSecurityExpressionHandler {
return ShiroMethodSecurityExpressionHandler()
}
}
class ShiroMethodSecurityExpressionHandler : DefaultMethodSecurityExpressionHandler() {
private val trustResolver = AuthenticationTrustResolverImpl()
override fun createSecurityExpressionRoot(authentication: Authentication, invocation: MethodInvocation): MethodSecurityExpressionOperations {
return ShiroMethodSecurityExpressionRoot(authentication).apply {
setPermissionEvaluator(permissionEvaluator)
setTrustResolver(trustResolver)
setRoleHierarchy(roleHierarchy)
}
}
}
open class ShiroMethodSecurityExpressionRoot(authentication: Authentication) : SecurityExpressionRoot(authentication), MethodSecurityExpressionOperations {
private var filterObject: Any? = null
private var returnObject: Any? = null
private var target: Any? = null
private val LOG = LoggerFactory.getLogger(ShiroMethodSecurityExpressionRoot::class.java)
override fun setFilterObject(filterObject: Any) {
this.filterObject = filterObject
}
override fun getFilterObject(): Any? {
return filterObject
}
override fun setReturnObject(returnObject: Any) {
this.returnObject = returnObject
}
override fun getReturnObject(): Any? {
return returnObject
}
/**
* Sets the "this" property for use in expressions. Typically this will be the "this"
* property of the `JoinPoint` representing the method invocation which is being
* protected.
*
* #param target the target object on which the method in is being invoked.
*/
fun setThis(target: Any) {
this.target = target
}
override fun getThis(): Any? {
return target
}
#Bean
open fun isPermitted(permission: String?): Boolean {
return true
}
#Bean
fun isPermitted(vararg permissions: String): Boolean {
return try {
val permissionObjects = permissions.map { permission -> WildcardPermission(permission) }
val user = this.principal as AuthAccount
//true
permissionObjects.all {
user.permissions.any { permission ->
permission.implies(it)
}
}
} catch (e: Exception) {
e.printStackTrace()
LOG.debug("", e)
throw (e)
}
}
}
Try to use text 'and' in the place of logical operator '&&'. I believe in #PreAuthorize annotation, you need to give text to combine multiple checks
My app is a basic news app which fetches data from JSON provided by Guardian API.
I parsed the values from JSON using raw java code (not using retrofit).
Then I get the LiveData in NewsFeedViewModel class which extends as AndroidViewModel.
And then in the fragment, I submit list to adapter.
These are the issues I'm facing:
1) at first, if the articles to show is set to 10, then if i go to settings and change it to 2, then the last 8 articles are disappearing but the white space /gap is not going. I can still scroll through the empty gap.
2) if i change the number of articles value constantly, then app is becoming un-scrollable.
And i have a few more doubts, how to refresh the data manually when swipeToRefresh is happened?
This is my project github link: https://github.com/sdzshn3/News24-7-RV
Video sample of the issue happening in app: https://drive.google.com/file/d/1gr_fabS2rqREuyecvGSG3IQ_jXOowlW7/view?usp=drivesdk
In kotlin style:
class RefreshableLiveData<T>(
private val source: () -> LiveData<T>
) : MediatorLiveData<T>() {
private var liveData = source()
init {
this.addSource(liveData, ::observer)
}
private fun observer(data: T) {
value = data
}
fun refresh() {
this.removeSource(liveData)
liveData = source()
this.addSource(liveData, ::observer)
}
}
Example:
class MainActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModel()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.goals.observe(this) { result ->
// update UI
}
// refresh
viewModel.refresh()
}
}
class MyViewModel(useCase: MyUseCase): ViewModel() {
private val _goals = RefreshableLiveData {
useCase.getGoals()
}
val goals: LiveData<Result<List<GoalItem>>>
get() = _goals.map(GoalItem::fromEntity)
fun refresh() {
_goals.refresh()
}
}
class MyUseCase {...}
...
You need to do exactly what I did in this Reddit post:
public class RefreshLiveData<T> extends MutableLiveData<T> {
public interface RefreshAction<T> {
private interface Callback<T> {
void onDataLoaded(T t);
}
void loadData(Callback<T> callback);
}
private final RefreshAction<T> refreshAction;
private final Callback<T> callback = new RefreshAction.Callback<T>() {
#Override
public void onDataLoaded(T t) {
postValue(t);
}
};
public RefreshLiveData(RefreshAction<T> refreshAction) {
this.refreshAction = refreshAction;
}
public final void refresh() {
refreshAction.loadData(callback);
}
}
Then you can do
public class YourViewModel extends ViewModel {
private final GithubRepository githubRepository;
public YourViewModel(GithubRepository githubRepository, SavedStateHandle savedStateHandle) {
this.githubRepository = githubRepository;
}
private final LiveData<String> userId = savedStateHandle.getLiveData("userId"); // from args
private final RefreshLiveData<List<Project>> refreshLiveData = Transformations.switchMap(userId, (uId) -> {
return githubRepository.getProjectList(uId);
});
public void refreshData() {
refreshLiveData.refresh();
}
public LiveData<List<Project>> getProjects() {
return refreshLiveData;
}
}
And then repository can do:
public RefreshLiveData<List<Project>> getProjectList(String userId) {
final RefreshLiveData<List<Project>> liveData = new RefreshLiveData<>((callback) -> {
githubService.getProjectList(userId).enqueue(new Callback<List<Project>>() {
#Override
public void onResponse(Call<List<Project>> call, Response<List<Project>> response) {
callback.onDataLoaded(response.body());
}
#Override
public void onFailure(Call<List<Project>> call, Throwable t) {
}
});
});
return liveData;
}
I'm trying to save object in background by using Parse.com but I can't override
override fun done(e: ParseException?) {
//code
}
I'm getting error: Modifier 'override' is not applicable to 'local function
In java I would use:
myObject.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
if (e == null) {
myObjectSavedSuccessfully();
} else {
myObjectSaveDidNotSucceed();
}
}
});
Here is my whole class
class StarterApplication : Application() {
override fun onCreate() {
super.onCreate()
Parse.initialize(Parse.Configuration.Builder(this)
.applicationId(appID)
.clientKey(null)
.server(serverUrl)
.build()
)
var exampleObject: ParseObject = ParseObject("ExampleObject")
exampleObject.put("myString", "fwfwe")
exampleObject.saveInBackground( {
override fun done(e: ParseException?) { //here is an error //`Modifier 'override' is not applicable to 'local function`
}
})
}
}
Just do like that:
exampleObject.saveInBackground(object : SaveCallback {
override fun done(e: ParseException?) {
// Add your code here
}
})
In Java, you declare an anonymous class that extend SaveCallback. In Kotlin, you do this with Object Expressions.
you can also try the simplest solution like this
exampleObject.saveInBackground({
//you code here
})
https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
I have the following Java class I'm trying to convert to Kotlin that uses generics.
abstract class MvpViewHolder, M, V : View?>(itemView: View) : RecyclerView.ViewHolder(itemView) {
public abstract class MvpViewHolder<P extends BasePresenter> extends RecyclerView.ViewHolder {
protected P presenter;
public MvpViewHolder(View itemView) {
super(itemView);
}
public void bindPresenter(P presenter) {
this.presenter = presenter;
presenter.bindView(this);
}
public void unbindPresenter() {
presenter = null;
}
}
Here is my Kotlin attempt
abstract class MvpViewHolder<P : BasePresenter>(itemView: View) : RecyclerView.ViewHolder(itemView) {
protected var presenter: P? = null
fun bindPresenter(presenter: P?): Unit {
this.presenter = presenter
presenter?.bindView(this)
}
fun unbindPresenter(): Unit {
this.presenter = null
}
}
I'm particularly running into a problem with the generics. It turns out that in Kotlin it's simply not enough to do MvpViewHolder<P : BasePresenter> as Kotlin requires that we pass in the 2 type arguments for BasePresenter (whose implementation I put below)
However, if I need to pass in the type arguments for BasePresenter then my method signature would then look like this
`abstract class MvpViewHolder<P : BasePresenter<*, *>>(itemView: View) : RecyclerView.ViewHolder(itemView) {`
This does not help me however, because in presenter.bindView(this) I get a type error of Required: Nothing, Found: MvpViewHolder
I could also get more specific and pass in
MvpViewHolder<P: BasePresenter<M, V>, M, V> but then that would mean that wherever I call MvpViewHolder, I then also have to include 2 extra type parameters. Not only will that be tedious to deal with now having to maintain, but it just makes me sad.
How can I either get rid of the error when I use BasePresenter<,> or avoid having to pass in 3 type parameters into my MvpViewHolder class, just so I can define P as a BasePresenter
abstract class BasePresenter<M, V> {
var model: M? = null
var view: WeakReference<V>? = null
fun setM(model: M?): Unit {
this.model = model
if (setupDone()) {
updateView()
}
}
fun bindView(view: V) {
this.view = WeakReference(view)
}
fun unbindView() {
this.view = null
}
abstract fun updateView()
fun view(): V? {
return if (view == null) null else view?.get()
}
fun setupDone(): Boolean {
return view() != null && model != null
}
}
Change abstract class to the following code
abstract class MvpViewHolder<P :BasePresenter<P,MvpViewHolder<P>>>(itemView: View) : RecyclerView.ViewHolder(itemView) {
protected var presenter: P? = null
fun bindPresenter(presenter: P) {
this.presenter = presenter
presenter.bindView(this)
}
fun unbindPresenter() {
presenter = null
}
}