Почему происходит ошибка "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<>();
→ Ссылка