Как из Java-класса вызвать функцию, реализованную на Kotlin в другом классе?
Как вызвать функцию Kotlin из другого пакета в Java-классе?
Имеется пакет fcmpushnotificationshttpv1
с классом, реализованным на Kotlin в файле ChatViewModel.kt
.
Также имеется пакет dem.corp.androidmessenger
с классом NewChatFragment
.
Я хочу из класса NewChatFragment
вызвать функцию sendMessage
, которая находится в другом пакете в классе ChatViewModel
.
Для этого я пишу такой код:
//ymy NEW test
new fcmpushnotificationshttpv1.ChatViewModel.ChatViewModel();
fcmpushnotificationshttpv1.sendMessage(true);
Но получаю ошибку компиляции:
C:\androidSDK\AndroidStudioProjects\AndroidMessenger-main\app\src\main\java\dem\corp\androidmessenger\bottomnav\new_chat\NewChatFragment.java:56: error: package fcmpushnotificationshttpv1.ChatViewModel does not exist
new fcmpushnotificationshttpv1.ChatViewModel.ChatViewModel();
Структура проекта и список пакетов следующие:
Почему не видит этот пакет?
Не помогает даже //import com.plcoding.fcmpushnotificationshttpv1.ChatViewModel;
Также не видит пакет SDK.
Я написал как сказал Nowhere Man, но выдает ошибку:
C:\androidSDK\AndroidStudioProjects\AndroidMessenger-main\app\src\main\java\dem\corp\androidmessenger\bottomnav\new_chat\NewChatFragment.java:30: error: package fcmpushnotificationshttpv1 does not exist
import fcmpushnotificationshttpv1.ChatViewModel;
^
Вот содержимое файла NewChatFragment.java
:
package dem.corp.androidmessenger.bottomnav.new_chat;
import static androidx.fragment.app.FragmentManager.TAG;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
//import fcmpushnotificationshttpv1.ChatViewModel;
//import fcmpushnotificationshttpv1.ChatViewModel;
import java.util.ArrayList;
import dem.corp.androidmessenger.databinding.FragmentNewChatBinding;
import dem.corp.androidmessenger.users.User;
import dem.corp.androidmessenger.users.UsersAdapter;
//import fcmpushnotificationshttpv1.ChatViewModel;
//import fcmpushnotificationshttpv1.ChatViewModel;
//import fcmpushnotificationshttpv1.ChatViewModel;
//import fcmpushnotificationshttpv1.ChatViewModel;
//import fcmpushnotificationshttpv1.ChatViewModel;
public class NewChatFragment extends Fragment {
private FragmentNewChatBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentNewChatBinding.inflate(inflater, container, false);
loadUsers();
return binding.getRoot();
}
private void loadUsers(){
ArrayList<User> users = new ArrayList<User>();
FirebaseDatabase.getInstance().getReference().child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot userSnapshot : snapshot.getChildren()){
if (userSnapshot.getKey().equals(FirebaseAuth.getInstance().getCurrentUser().getUid())){
continue;
}
//ymy NEW test
// вызов конструктора класса ChatViewModel
// вызов конструктора класса ChatViewModel
ChatViewModel chatViewModel = new fcmpushnotificationshttpv1.ChatViewModel();
// вызов package-level функции
fcmpushnotificationshttpv1.ChatViewModel.sendMessage(true);
// вызов package-level функции
fcmpushnotificationshttpv1.ChatViewModel.sendMessage(true);
// ChatViewModel.sendMessage(true);
// new fcmpushnotificationshttpv1.ChatViewModel();
// fcmpushnotificationshttpv1.ChatViewModel.class.
//my test OK
//показывает flase у всех юзеров String username = String.valueOf(userSnapshot.getKey().equals(FirebaseAuth.getInstance().getCurrentUser().getUid()));
String username = userSnapshot.child("username").getValue().toString();
Log.w(TAG, "Error getting documents. 2222 username=" + username);
String uid = userSnapshot.getKey();
Log.w(TAG, "Error getting documents. 2222 uid=" + uid);
//String username = Objects.requireNonNull(userSnapshot.child("username").getValue()).toString();
String profileImage = String.valueOf(userSnapshot.child("profileImage").getValue());
users.add(new User(uid, username, profileImage));
}
binding.usersRv.setLayoutManager(new LinearLayoutManager(getContext()));
binding.usersRv.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
binding.usersRv.setAdapter(new UsersAdapter(users));
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
}
}
Вот содержимое файла ChatViewModel.kt
:
@file:JvmName("ChatViewModel")
package fcmpushnotificationshttpv1
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.firebase.ktx.Firebase
import com.google.firebase.messaging.ktx.messaging
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import retrofit2.HttpException
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.create
import java.io.IOException
class ChatViewModel: ViewModel() {
var state by mutableStateOf(ChatState())
private set
private val api: FcmApi = Retrofit.Builder()
// .baseUrl("http://10.0.2.2:8084/")
.baseUrl("http://109.195.103.21:8084/")
.addConverterFactory(MoshiConverterFactory.create())
.build()
.create()
init {
viewModelScope.launch {
Firebase.messaging.subscribeToTopic("chat").await()
}
}
fun onRemoteTokenChange(newToken: String) {
state = state.copy(
remoteToken = newToken
)
}
fun onSubmitRemoteToken() {
state = state.copy(
isEnteringToken = false
)
}
fun onMessageChange(message: String) {
state = state.copy(
messageText = message
)
}
fun sendMessage(isBroadcast: Boolean) {
viewModelScope.launch {
val messageDto = SendMessageDto(
to = if(isBroadcast) null else state.remoteToken,
notification = NotificationBody(
title = "New message!",
body = state.messageText
)
)
try {
if(isBroadcast) {
api.broadcast(messageDto)
} else {
api.sendMessage(messageDto)
}
state = state.copy(
messageText = ""
)
} catch(e: HttpException) {
e.printStackTrace()
} catch(e: IOException) {
e.printStackTrace()
}
}
}
}
Ответы (1 шт):
Обновление
После предоставления Kotlin-кода выяснилось, что он НЕ содержит функции уровня пакета, зато в нём есть функция-член класса ChatViewModel
:
package fcmpushnotificationshttpv1
class ChatViewModel {
fun sendMessage(isBroadcast: Boolean) {
println("sendMessage: broadcast=$isBroadcast")
}
}
Соответственно, в Java-коде она должна вызываться для соответствующего экземпляра:
- с импортом класса
package dem.corp.androidmessenger.bottomnav.new_chat;
import fcmpushnotificationshttpv1.ChatViewModel;
public class NewChatFragment {
public void loadUsers() {
ChatViewModel chatViewModel = new ChatViewModel();
chatViewModel.sendMessage(true);
}
}
- или без импорта, с указанием имени пакета
package dem.corp.androidmessenger.bottomnav.new_chat;
public class NewChatFragment {
public void loadUsers() {
var chatViewModel = new fcmpushnotificationshttpv1.ChatViewModel();
chatViewModel.sendMessage(true);
}
}
ЕСЛИ БЫ на уровне пакета была определена некая другая функция, то судя по документации Calling Kotlin from Java: Package-level functions, её можно было бы вызвать следующим образом:
import fcmpushnotificationshttpv1.*; // импорт из Kotlin-пакета
// вызов конструктора класса ChatViewModel
var chatViewModel = new ChatViewModel();
chatViewModel.sendMessage(true);
// вызов package-level функции
ChatViewModelUtil.packageFoo();
при условии, что файл ChatViewModel.kt
содержит аннотацию:
@file:JvmName("ChatViewModelUtil")
package fcmpushnotificationshttpv1
class ChatViewModel {
/* реализация класса */
fun sendMessage(b: Boolean) {
/* реализация функции-члена*/
}
}
fun packageFoo() {
/* реализация пакетной функции */
}
Важно: Если Kotlin-класс ChatViewModel
находится в файле ChatViewModel.kt
, но в нём НЕ используется аннотация @file:JvmName
, то название класса, содержащего функцию уровня пакета packageFoo
и доступного в JVM будет fcmpushnotificationshttpv1.ChatViewModelKt
, то есть, в Java-коде будет доступен статический метод:
// java-код
fcmpushnotificationshttpv1.ChatViewModelKt.packageFoo();
Об этом также указано в документации, приведённой по ссылке.