【问题标题】:Firebase recycler view does not show images on recycler view [closed]Firebase 回收站视图不会在回收站视图上显示图像 [关闭]
【发布时间】:2022-01-16 13:35:37
【问题描述】:

我是新来的工作火力基地。我设法上传了文本和图像,但是,我无法检索要显示到我的回收站视图中的图像,只能检索文本。 我正在使用毕加索依赖项。我已经包含了我的 MainActivity.java 类,该类负责显示从问题中的 firebase 检索到的回收器视图项目,即我的适配器。 java类和模型类。我相信当我将 图像 URI 上传到 Firebase 存储时,我可能犯了一个错误,因此适配器无法检索图像位置。我认为可能是这种情况,因为我在研究问题时遇到了类似的情况。请帮忙

下面是我的模型 java 类的代码

public class Model {

    // string variable for
    // storing employee name.
    private String journeyName;

    // string variable for storing
    // employee contact number
    private String journeyDescription;

    // string variable for storing
    // employee address.
    private String journeyLocation;

    //lets experiment with an id
    private String journeyId;

    //an url for an image
    private String imageURL;

    // an empty constructor is
    // required when using
    // Firebase Realtime Database.


    public Model() {

    }

    protected Model(Parcel in){
        journeyName = in.readString();
        journeyDescription = in.readString();
        journeyLocation = in.readString();
        journeyId = in.readString();
        imageURL = in.readString();
    }

    public static final Parcelable.Creator<Model> CREATOR = new Parcelable.Creator<Model>(){
        @Override
        public Model createFromParcel(Parcel in) {
            return new Model(in);
        }

        @Override
        public Model[] newArray(int size) {
            return new Model[size];
        }
    };



    // created getter and setter methods
    // for all our variables.
    public String getJourneyName() {
        return journeyName;
    }

    public void setJourneyName(String journeyName) {
        this.journeyName = journeyName;
    }

    public String getJourneyDescription() {
        return journeyDescription;
    }

    public void setJourneyDescription(String journeyDescription) {
        this.journeyDescription = journeyDescription;
    }

    public String getJourneyLocation() {
        return journeyLocation;
    }

    public void setJourneyLocation(String journeyLocation) {
        this.journeyLocation = journeyLocation;
    }

    public String getJourneyId() {
        return journeyId;
    }

    public void setJourneyId(String journeyId) {
        this.journeyId = journeyId;
    }

    public String getImageURL() {
        return imageURL;
    }

    public void setImageURL(String imageURL) {
        this.imageURL = imageURL;
    }

    public Model(String journeyName, String journeyDescription, String journeyLocation, String journeyId, String url) {

        this.journeyName = journeyName;
        this.journeyDescription = journeyDescription;
        this.journeyLocation = journeyLocation;
        this.journeyId = journeyId;
        this.imageURL = url;
    }


    public int describeContents() {
        return 0;
    }


    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(journeyName);
        dest.writeString(journeyDescription);
        dest.writeString(journeyLocation);
        dest.writeString(journeyId);
        dest.writeString(imageURL);
    }
}

下面是我的适配器代码

public class JourneyRVAdapter extends RecyclerView.Adapter<JourneyRVAdapter.ViewHolder>{

    //creating variables for our list, context interface and position
    private ArrayList<Model> modelArrayList;
    private Context context;
    private JourneyClickInterface journeyClickInterface;
    int lastPos = -1;

    //creating a constructor
    public JourneyRVAdapter(ArrayList<Model> modelArrayList, Context context, JourneyClickInterface journeyClickInterface) {
        this.modelArrayList = modelArrayList;
        this.context = context;
        this.journeyClickInterface = journeyClickInterface;

    }

    @NonNull
    @Override
    public JourneyRVAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //inflating our layout file below on line
        View view = LayoutInflater.from(context).inflate(R.layout.row, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        //setting data to our recycler view item on below line.
        Model model = modelArrayList.get(position);
        holder.titleTV.setText(model.getJourneyName());
        holder.DescTV.setText(model.getJourneyDescription());
        holder.LocationTV.setText(model.getJourneyLocation());

        Picasso.get().load(model.getImageURL()).placeholder(R.mipmap.ic_launcher)
                .fit()
                .centerCrop()
                .into(holder.imageIV);

        // adding animation to recycler view item on below line.
        setAnimation(holder.itemView, position);
        holder.rowLY.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                journeyClickInterface.onJourneyClick(position);
            }
        });

    }

    private void setAnimation(View itemView, int position) {
        ///animations implement own logic!!!
        if (position > lastPos) {
            // on below line we are setting animation.
            Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
            itemView.setAnimation(animation);
            lastPos = position;
        }
    }

    @Override
    public int getItemCount() {
      return modelArrayList.size();
       // return (modelArrayList == null) ? 0 : modelArrayList.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        //creating variable for our imageview and text views below
        private ImageView imageIV;
        private TextView titleTV, DescTV, LocationTV;
        private LinearLayout rowLY;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            //initializing all our variables on below line
            imageIV = itemView.findViewById(R.id.rImageView);
            titleTV = itemView.findViewById(R.id.rTitleView);
            DescTV = itemView.findViewById(R.id.rDescriptionTv);
            LocationTV = itemView.findViewById(R.id.rLocationTv);
            rowLY = itemView.findViewById(R.id.cardRow);


        }
    }

    // creating an interface for on click
    public interface JourneyClickInterface {
        void onJourneyClick(int position);
    }
}

主要活动的代码这是我将显示我的回收站视图项目的地方

public class MainActivity extends AppCompatActivity {

    private FloatingActionButton FloatingActionButton;

    // creating variables for fab, firebase database,
    // progress bar, list, adapter,firebase auth,
    // recycler view and relative layout.
    private FirebaseDatabase firebaseDatabase;

    StorageReference storageReference;

    private DatabaseReference databaseReference;

    private RecyclerView journeyRV;

    private FirebaseAuth mAuth;
    //private ProgressBar loadingPB;

    private ArrayList<Model> modelArrayList;

    private JourneyRVAdapter journeyRVAdapter;

    private RelativeLayout homeRL;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FloatingActionButton = findViewById(R.id.floatingActionButton);
        //initialize
        journeyRV = findViewById(R.id.idRVJourneys);
        //homeRL = findViewById(R.id.)
        //loadingPB
        firebaseDatabase = FirebaseDatabase.getInstance();
        mAuth = FirebaseAuth.getInstance();
        modelArrayList = new ArrayList<>();
        //on below line we are getting database reference.
        databaseReference = firebaseDatabase.getReference("Journeys");

        //reference for our storage db
        storageReference = FirebaseStorage.getInstance().getReference("images1");

        // on below line adding a click listener for our floating action button.
        FloatingActionButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this, AddActivity.class));
            }
        });
        // on below line initializing our adapter class.
        journeyRVAdapter = new JourneyRVAdapter(modelArrayList, this, this::onJourneyClick);
        //setting layout manager to recycler view on below line
        journeyRV.setLayoutManager(new LinearLayoutManager(this));
        // setting adapter to recycler view on below line.
        journeyRV.setAdapter(journeyRVAdapter);
        //on below line calling a method to fetch courses from database
        getJourneys();

    }

    private void getJourneys() {
        //on below line we are clearing our list
        modelArrayList.clear();
        //on below line we are calli g add child event listener methods to read the data
        databaseReference.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                //hide progress bar

                //then add snap shot to our array list on below line
                modelArrayList.add(snapshot.getValue(Model.class));
                //notify our adapter that data has changed
                journeyRVAdapter.notifyDataSetChanged();
            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                //this method is called when new child is added
                // we are notifying our adapter and making progress bar
                // visibility as gone.
                //loadingPB.setVisibility(View.GONE);
                journeyRVAdapter.notifyDataSetChanged();
            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot snapshot) {
                // notifying our adapter when child is removed.
                journeyRVAdapter.notifyDataSetChanged();
                //loadingPB.setVisibility(View.GONE);

            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
                // notifying our adapter when child is moved.
                //loadingPB.setVisibility(View.GONE);
                journeyRVAdapter.notifyDataSetChanged();

            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                Toast.makeText(getApplicationContext(), " " + error, Toast.LENGTH_SHORT).show();
            }
        });
    }
 }

向我的 firebase 实时数据库和存储添加新条目/记录的代码

public class AddActivity extends AppCompatActivity {

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add);

        //initializing our edt and btn
        journeyNameEdt = findViewById(R.id.idEdtJourneyName);
        journeyDescriptionEdt = findViewById(R.id.idEdtJourneyDescription);
        journeyLocationEdt = findViewById(R.id.idEdtJourneyLocation);

        // for myn image view
        imgView = findViewById(R.id.image_view);

        //get instance of our firebase database
        firebaseDatabase = FirebaseDatabase.getInstance();

        //reference for our storage db
        storageReference = FirebaseStorage.getInstance().getReference("images1");

        //get reference of our database
        databaseReference = firebaseDatabase.getReference("Journeys");

        //initializing our object
        //class variable
        model = new Model();

        sendDatabtn = findViewById(R.id.idBtnSendData);

        btnbrowse = findViewById(R.id.btnbrowse);

        //browse imagery
        btnbrowse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent, "Select Image"), Image_Request_Code);
            }
        });

        //adding an onClick listener for sending data
        sendDatabtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if(FilePathUri != null){
                String journey = journeyNameEdt.getText().toString();
                String description = journeyDescriptionEdt.getText().toString();
                String location = journeyLocationEdt.getText().toString();
                String url = FilePathUri.getPath();
                journeyId = journey;

                //below line is for checking weather the edittext files are empty or not
                Model model = new Model(journeyId, journey, description, location,url);


                addDataFirebase(journey, description, location);

                UploadImage();}
                else{
                    Toast.makeText(getApplicationContext(), "Please make selection ", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == Image_Request_Code && resultCode == RESULT_OK && data != null && data.getData() != null){

            FilePathUri = data.getData();

            try{
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), FilePathUri);
                imgView.setImageBitmap(bitmap);
            }
            catch (IOException e){
                e.printStackTrace();
            }

        }
    }

    public String GetFileExtension (Uri uri){

        ContentResolver contentResolver = getContentResolver();
        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
        return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri));
    }

    public void UploadImage(){

        if (FilePathUri != null) {
            StorageReference storageReference1 = storageReference.child(System.currentTimeMillis()+ "."+ GetFileExtension(FilePathUri));
            storageReference1.putFile(FilePathUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                    Toast.makeText(getApplicationContext(), "Image uploaded", Toast.LENGTH_SHORT).show();


                }
            });
        }else{
            Toast.makeText(AddActivity.this, "Please Select Image or Add Image Name", Toast.LENGTH_SHORT).show();
        }
    }

    private void addDataFirebase (String journey, String description, String location){
        // these below lines are used to set data in our object class
        model.setJourneyName(journey);
        model.setJourneyDescription(description);
        model.setJourneyLocation(location);

        //we are to use an add value event listener method
        //this is called with database reference
        databaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                //inside here we are setting our object class to our database reference
                //database reference will send data to firebase

                databaseReference.child(journeyId).setValue(model);

                //databaseReference.setValue(model);

                //if successful show toast
                Toast.makeText(AddActivity.this, "data added", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                //if failed show toast
                Toast.makeText(AddActivity.this, "Failed to add data"+ error, Toast.LENGTH_SHORT).show();
            }
        });
    }

}

下面显示我的实时数据库节点

【问题讨论】:

  • 顺便说一下,Logcat 面板上没有显示错误
  • "我认为我在将图像 URI 上传到 firebase 存储时可能犯了一个错误" - 你是说你不知道吗如果您存储了图像 URL?这不是我们可以帮助您的事情。您必须自己检查并进行一些调试以找出问题所在。
  • 是否检查过数据库中的值是否存在
  • 实时数据库中不存在 URL 值,但代码设法使用 URL 将图像上传到 Firebase 存储

标签: java android firebase android-recyclerview firebase-storage


【解决方案1】:

您可以在 Firebase 中添加更多字段来保存 imageUrl,如果您想要获取 imageUrl,您可以在 UploadImage 方法上添加以下代码。

public void UploadImage(){

    if (FilePathUri != null) {
        StorageReference storageReference1 = storageReference.child(System.currentTimeMillis()+ "."+ GetFileExtension(FilePathUri));
        storageReference1.putFile(FilePathUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                storageReference1.getDownloadUrl().addOnSuccessListener(uri -> { url = uri.toString(); }
                Toast.makeText(getApplicationContext(), "Image uploaded", Toast.LENGTH_SHORT).show();


            }
        });
    }else{
        Toast.makeText(AddActivity.this, "Please Select Image or Add Image Name", Toast.LENGTH_SHORT).show();
    }
}

所以imageUrl的值是Firestorage的Url,Picasso加载的Url是Firestorage的Url。

【讨论】:

    【解决方案2】:

    我会用这个方法上传照片 它是高度安全的,也可以在后台运行,因此用户不能故意停止图像加载并发生错误: // 你也可以上传多张照片,而不仅仅是一张

    public class UploadImageService extends IntentService {
        public UploadImageService () {
            super("UploadImageService ");
        }
    
        protected FirebaseFirestore db; // this Code if youe using Firestore only
        protected DocumentReference user_doc ; // this Code if youe using Firestore only
        // if Firebase RealTime Just Remove `db` An `usee_doc`
        protected ArrayList<String> Urix = new ArrayList<>();
        protected FirebaseStorage storage = FirebaseStorage.getInstance();
        protected StorageReference storageRef = storage.getReference().child(Objects.requireNonNull(FirebaseAuth.getInstance().getUid()));
        
    
        protected String Post_Key;
    
        @Override
        protected void onHandleIntent(Intent workIntent) {
    
            Urix = workIntent.getExtras().getStringArrayList("Uri");
            Post_Key = workIntent.getExtras().getString("Post_Key");
            db = FirebaseFirestore.getInstance();
    
            for (int i = 0; i < Urix.size(); i++)
            {
                SendThis(i);
            }
    
    
    
        }
    
    
        public void SendThis (int Currrents)
        {
    
            final String Current = Urix.get(Currrents);
            File file = new File(Urix.get(Currrents));
    
            int fin = getRandomNumber(900) * getRandomNumber(900) + getRandomNumber(10000) ;
    
            storageRef.child(getRandomNumber(10000) + file.getName() + fin  ).putFile(Uri.parse(Urix.get(Currrents)))
                    .addOnSuccessListener(taskSnapshot -> taskSnapshot.getStorage().getDownloadUrl().addOnSuccessListener(uri -> {
                        
                        Update(uri.toString());
                    }))
                    .addOnFailureListener(e -> {
    
                    });
    
        }
    
    
        private void Update(String url)
        {
            //Post Key to get child path
            // url is your image URL 
            // Now Just get your child path and add the image url
    
    
        }
    
        private int getRandomNumber(int max) {
            return (new Random()).nextInt((max - 1) + 1) + 1;
        }
    

    }

    //在你的 Action 'UploadImageActivity or Main Activity' 中添加这个代码来启动任务:

    public void SendThis (String XS)
    {
        Intent intent = new Intent(CreateUploadTitle.this ,UploadImageService.class);
        
        intent.putExtra("Uri" , YourCurrentImagePath);
        intent.putExtra("Post_Key" , yourPostKeyAfterUploadData);
        startService(intent);
    }
    

    // 在你的主要活动中:

     <service android:name=".PostSystem.Server.UploadVideoService"
                android:exported="false" />
    

    // 现在要获取您的图像,只需在您的数据库中获取名称 // 如果你有正确的Firebase ruls

    【讨论】: