Почему происходит ошибка "Unchecked call to 'addOnCompleteListener(OnCompleteListener)'"?
В общем пишу приложение и не пойму, что сделал не так, выдает такую ошибку:
"Unchecked call to 'addOnCompleteListener(OnCompleteListener)' as a member of raw type 'com.google.android.gms.tasks.Task’"
Мой код:
public class UserSet extends AppCompatActivity {
private CircleImageView profileImageView;
private EditText fullNameEditText, userPhoneEditText, addressEditText;
private TextView saveTextButton, closeTextBtn;
private String checker = "";
private StorageReference storageProfilePictureRef;
private StorageTask uploadTask;
private Uri imageUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_set);
profileImageView = (CircleImageView) findViewById(R.id.settings_account_image);
fullNameEditText = (EditText) findViewById(R.id.settings_fullname);
userPhoneEditText = (EditText) findViewById(R.id.settings_phone);
addressEditText = (EditText) findViewById(R.id.settings_address);
saveTextButton = (TextView) findViewById(R.id.save_settings_tv);
closeTextBtn = (TextView) findViewById(R.id.close_settings_tv);
storageProfilePictureRef = FirebaseStorage.getInstance().getReference().child("Profile pictures");
userInfoDisplay(profileImageView, fullNameEditText, userPhoneEditText,addressEditText);
//
closeTextBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(UserSet.this, HomeActivity.class);
startActivity(intent);
}
});
saveTextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (checker.equals("clicked")){
userInfoSaved();
}
else{
updateOnlyUserInfo();
}
}
});
profileImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checker = "clicked";
CropImage.activity(imageUri)
.setAspectRatio(1,1)
.start(UserSet.this);
}
});
}
private void userInfoDisplay(final ImageView profileImageView,final EditText fullNameEditText,final EditText userPhoneEditText,final EditText addressEditText) {
String phone = Prevalent.currentOnlineUser.getPhone();
DatabaseReference UsersRef = FirebaseDatabase.getInstance().getReference().child("Users").child(phone);
UsersRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot)
{
if (dataSnapshot.exists())
{
if (dataSnapshot.child("image").exists())
{
String image = dataSnapshot.child("image").getValue().toString();
String name = dataSnapshot.child("name").getValue().toString();
String phone = dataSnapshot.child("phone").getValue().toString();
String address = dataSnapshot.child("address").getValue().toString();
Picasso.get().load(image).into(profileImageView);
fullNameEditText.setText(name);
userPhoneEditText.setText(phone);
addressEditText.setText(address);
}
if (dataSnapshot.child("address").exists())
{
String name = dataSnapshot.child("name").getValue().toString();
String phone = dataSnapshot.child("phone").getValue().toString();
String address = dataSnapshot.child("address").getValue().toString();
fullNameEditText.setText(name);
userPhoneEditText.setText(phone);
addressEditText.setText(address);
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE && resultCode==RESULT_OK && data!=null)
{
CropImage.ActivityResult result = CropImage.getActivityResult(data);
imageUri = result.getUri();
profileImageView.setImageURI(imageUri);
}
else
{
Toast.makeText(this, "Ошибка", Toast.LENGTH_SHORT).show();
startActivity(new Intent(UserSet.this, UserSet.class));
finish();
}
}
private void userInfoSaved() {
if(TextUtils.isEmpty(fullNameEditText.getText().toString())){
Toast.makeText(this, "Заполните имя", Toast.LENGTH_LONG).show();
}
else if (TextUtils.isEmpty(userPhoneEditText.getText().toString())){
Toast.makeText(this, "Заполните номер", Toast.LENGTH_LONG).show();
}
else if (TextUtils.isEmpty(addressEditText.getText().toString())){
Toast.makeText(this, "Заполните адрес", Toast.LENGTH_LONG).show();
}
else if (checker.equals("clicked")){
uploadImage();
}
}
private void uploadImage() {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Обновляем..");
progressDialog.setMessage("Пожалуйста подождите");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
if (imageUri != null)
{
final StorageReference fileRef = storageProfilePictureRef
.child(Prevalent.currentOnlineUser.getPhone() + ".WebP");
uploadTask = fileRef.putFile(imageUri);
` uploadTask.continueWithTask(new Continuation() {
@Override
public Object then(@NonNull Task task) throws Exception
{
if (!task.isSuccessful())
{
throw task.getException();
}
return fileRef.getDownloadUrl();
}
})
.addOnCompleteListener(new OnCompleteListener<Uri>(){`
@Override
public void onComplete(@NonNull Task<Uri> task){
if (task.isSuccessful())
{
Uri downloadUrl = task.getResult();
String myUrl = downloadUrl.toString();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users");
HashMap<String, Object> userMap = new HashMap<>();
userMap. put("name", fullNameEditText.getText().toString());
userMap. put("address", addressEditText.getText().toString());
userMap. put("phoneOrder", userPhoneEditText.getText().toString());
userMap. put("image", myUrl);
ref.child(Prevalent.currentOnlineUser.getPhone()).updateChildren(userMap);
progressDialog.dismiss();
startActivity(new Intent(UserSet.this, HomeActivity.class));
Toast.makeText(UserSet.this, "Информация успешно сохранена", Toast.LENGTH_SHORT).show();
finish();
}
else
{
progressDialog.dismiss();
Toast.makeText(UserSet.this, "Error.", Toast.LENGTH_SHORT).show();
}
}
});
}
else
{
Toast.makeText(this, "Изображение не выбрано.", Toast.LENGTH_SHORT).show();
}
}
private void updateOnlyUserInfo() {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users");
HashMap<String, Object> userMap = new HashMap<>();
userMap.put("name", fullNameEditText.getText().toString());
userMap.put("phone", userPhoneEditText.getText().toString());
userMap.put("adress", addressEditText.getText().toString());
ref.child(Prevalent.currentOnlineUser.getPhone()).updateChildren(userMap);
startActivity(new Intent(UserSet.this, HomeActivity.class));
Toast.makeText(UserSet.this, "", Toast.LENGTH_LONG).show();
finish();
}
Ошибка заключается в этом блоке, отметил.
Ответы (1 шт):
Что означает ошибка?
Строго говоря, это и не ошибка даже, а всего лишь предупреждение. Код скомпилируется и выполнится, но он будет небезопасен. Приведу ещё раз текст предупреждения, чтобы он был перед глазами:
"Unchecked call to 'addOnCompleteListener(OnCompleteListener)' as a member of raw type 'com.google.android.gms.tasks.Task’
Вам говорят, что вызов addOnCompleteListener(OnCompleteListener)
небезопасен, т.к объект, на который вызывается метод представляет сырой тип (англ. raw type).
Что такое сырой тип?
Это объект дженерик-класса, созданный без объявления типа данных в угловых скобках <>, например:
ArrayList list = new ArrayList();
Приведённый мною в примере java.util.ArrayList
является дженерик-классом, для того, чтобы в этом убедится, можно взглянуть на исходный код:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
....
Поэтому его объекты следует создавать, указывая тип данных, с которым планируете работать (ради примера я возьму String):
ArrayList<String> list = new ArrayList<String>();
С Java 7 можно короче и не писать тип второй раз:
ArrayList<String> list = new ArrayList<>();
Что вам следует сделать?
- Лучше всего найти участок кода и строчку, из-за которого возникло предупреждние. У вас это вот этот:
uploadTask.continueWithTask(new Continuation() {
@Override
public Object then(@NonNull Task task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return fileRef.getDownloadUrl();
}
})
.addOnCompleteListener(new OnCompleteListener<Uri>() {
@Override
public void onComplete(@NonNull Task<Uri> task) {
//И тут какой-то код...
}
Метод addOnCompleteListener()
вызывается на объект uploadTask
дженерик-класса StorageTask
:
public abstract class StorageTask<ResultT extends StorageTask.ProvideError> extends ControllableTask
Добавьте указание конкретного типа данных в угловых скобках <> при объявлении этого объекта:
private StorageTask uploadTask; //Тут надо добавить угловые скобки <> с каким-то типом данных
Но учтите, что есть ограничение extends StorageTask.ProvideError
, то есть тип в угловых скобках должен реализовывать интерфейс StorageTask.ProvideError
.
- Можно ничего не исправлять, а просто подавить предупреждение, но прежде чем это сделать, вам надо 7 раз подумать. Потому что предупреждения созданы не просто так, а с целью предотвратить неприятности. Но если всё же по какой-то причине вы считаете, что нужно поступить именно так, добавьте аннотацию
@SuppressWarnings("unchecked")
к методу, на который ругается компилятор.
P.S: всё написанное выше должно быть вам понятно, т.к вы в своём коде использовали дженерики, например:
HashMap<String, Object> userMap = new HashMap<>();