You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView新增Item时自动触发数据上传的实现方案问询

Automatically Upload Audio When New Item is Added to RecyclerView

Got it, let's adjust your RecyclerView Adapter so that when a new item is added, it automatically triggers the audio upload via postingData() method. Here's the modified code with key changes explained:

Key Changes Made:

  • Added a Set<String> uploadedFiles to track already uploaded audio files, preventing duplicate uploads
  • Created an addNewSong() method to safely add new items to the adapter and trigger auto-upload
  • Extracted network connectivity check into a reusable isNetworkConnected() method (updated to use modern API for Android 10+ compatibility)
  • Triggered upload logic right after notifying the adapter about the new item
  • Added proper null checks and error handling to avoid crashes
  • Added upload status UI updates (success/failure indicators)

class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
    public ArrayList<String> songNames;
    Context context;
    Handler seekHandler = new Handler();
    Runnable run;
    // Track uploaded files to avoid duplicate upload attempts
    private Set<String> uploadedFiles = new HashSet<>();
    // Reference to RecyclerView to access view holders for new items
    private RecyclerView recyclerView;

    public RecyclerViewAdapter(ArrayList<String> songNames, Context context) {
        this.songNames = songNames;
        this.context = context;
        // Uncomment below if you don't want to upload existing items on adapter initialization
        // uploadedFiles.addAll(songNames);
    }

    // Attach RecyclerView reference when setting adapter
    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        this.recyclerView = recyclerView;
    }

    // Method to add new song and trigger auto-upload
    public void addNewSong(String songPath) {
        songNames.add(songPath);
        int newItemPosition = songNames.size() - 1;
        notifyItemInserted(newItemPosition);
        
        // Trigger auto-upload for the new item
        if (isNetworkConnected()) {
            Toast.makeText(context, "Starting audio upload...", Toast.LENGTH_SHORT).show();
            // Get view holder for the new position (if it's already bound to UI)
            MyViewHolder holder = (MyViewHolder) recyclerView.findViewHolderForAdapterPosition(newItemPosition);
            postingData(newItemPosition, holder);
        } else {
            Toast.makeText(context, "No internet connection - upload will retry later", Toast.LENGTH_SHORT).show();
            // Optional: Add to a pending upload queue to retry when network is restored
        }
    }

    @NonNull
    @Override
    public RecyclerViewAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View listItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.record_card, parent, false);
        return new MyViewHolder(listItem);
    }

    @Override
    public void onBindViewHolder(@NonNull final RecyclerViewAdapter.MyViewHolder holder, final int position) {
        final String currentSongPath = songNames.get(position);
        holder.textView.setText(currentSongPath);

        // Keep manual upload option if needed
        holder.textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                holder.playerCard.setVisibility(View.VISIBLE);
                if (isNetworkConnected()) {
                    Toast.makeText(context, "Internet is active", Toast.LENGTH_SHORT).show();
                    postingData(position, holder);
                } else {
                    Toast.makeText(context, "No internet connection", Toast.LENGTH_SHORT).show();
                }
            }
        });

        // Existing media player controls (unchanged)
        holder.cardView1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                holder.playerCard.setVisibility(View.VISIBLE);
            }
        });

        final MediaPlayer mediaPlayer = new MediaPlayer();
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        try {
            mediaPlayer.setDataSource(currentSongPath);
            mediaPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }

        holder.seekBar.setMax(mediaPlayer.getDuration());
        holder.seekBar.setTag(position);
        holder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (mediaPlayer != null && fromUser) {
                    mediaPlayer.seekTo(progress);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });

        holder.seekBarHint.setText("0:00/" + calculateDuration(mediaPlayer.getDuration()));

        holder.playsong.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!mediaPlayer.isPlaying()) {
                    mediaPlayer.start();
                    holder.pauseRec.setVisibility(View.VISIBLE);
                    holder.playsong.setVisibility(View.INVISIBLE);
                    holder.playsong.setText(" Pause ");
                    run = new Runnable() {
                        @Override
                        public void run() {
                            holder.seekBar.setProgress(mediaPlayer.getCurrentPosition());
                            seekHandler.postDelayed(run, 100);
                            int miliSeconds = mediaPlayer.getCurrentPosition();
                            if (miliSeconds != 0) {
                                long minutes = TimeUnit.MILLISECONDS.toMinutes(miliSeconds);
                                long seconds = TimeUnit.MILLISECONDS.toSeconds(miliSeconds);
                                if (minutes == 0) {
                                    holder.seekBarHint.setText("0:" + seconds + "/" + calculateDuration(mediaPlayer.getDuration()));
                                } else {
                                    if (seconds >= 60) {
                                        long sec = seconds - (minutes * 60);
                                        holder.seekBarHint.setText(minutes + ":" + sec + "/" + calculateDuration(mediaPlayer.getDuration()));
                                    }
                                }
                            } else {
                                int totalTime = mediaPlayer.getDuration();
                                long minutes = TimeUnit.MILLISECONDS.toMinutes(totalTime);
                                long seconds = TimeUnit.MILLISECONDS.toSeconds(totalTime);
                                if (minutes == 0) {
                                    holder.seekBarHint.setText("0:" + seconds);
                                } else {
                                    if (seconds >= 60) {
                                        long sec = seconds - (minutes * 60);
                                        holder.seekBarHint.setText(minutes + ":" + sec);
                                    }
                                }
                            }
                        }
                    };
                    run.run();
                } else {
                    mediaPlayer.pause();
                    holder.pauseRec.setVisibility(View.INVISIBLE);
                    holder.playsong.setVisibility(View.VISIBLE);
                    holder.playsong.setText(" Play ");
                }
            }
        });

        holder.pauseRec.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mediaPlayer.pause();
                holder.playsong.setVisibility(View.VISIBLE);
                holder.pauseRec.setVisibility(View.GONE);
            }
        });

        // Show upload status if already uploaded
        if (uploadedFiles.contains(currentSongPath)) {
            holder.recdonpost.setVisibility(View.VISIBLE);
            holder.notdone.setVisibility(View.GONE);
        } else {
            holder.recdonpost.setVisibility(View.GONE);
            holder.notdone.setVisibility(View.VISIBLE);
        }
    }

    private void postingData(final int position, final MyViewHolder holder) {
        final String songPath = songNames.get(position);
        // Skip upload if already completed
        if (uploadedFiles.contains(songPath)) {
            Toast.makeText(context, "Audio already uploaded", Toast.LENGTH_SHORT).show();
            return;
        }

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        final String userId = preferences.getString("user_id", "0");
        String currentTime = preferences.getString("currentDate", "1");
        SharedPreferences sp = context.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
        String prospectNumber = sp.getString("prospectNumber", "1234567891");
        System.out.println("prospectNumber: " + prospectNumber);

        OkHttpClient client = new OkHttpClient();
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", songPath, RequestBody.create(MediaType.parse("application/octet-stream"), new File(songPath)))
                .addFormDataPart("user_id", userId)
                .addFormDataPart("file_name", "Call Recording")
                .addFormDataPart("creation_datetime", currentTime)
                .addFormDataPart("prospect_number", prospectNumber)
                .addFormDataPart("call_type","incoming")
                .build();

        Request request = new Request.Builder()
                .url("http://159.65.145.32/api/file/upload/")
                .post(requestBody)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
                uploadedFiles.remove(songPath);
                // Update UI on main thread
                ((Activity)context).runOnUiThread(() -> {
                    Toast.makeText(context, "Upload failed - please try again", Toast.LENGTH_SHORT).show();
                    if (holder != null) {
                        holder.notdone.setVisibility(View.VISIBLE);
                        holder.recdonpost.setVisibility(View.GONE);
                    }
                });
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                if (!response.isSuccessful()) {
                    throw new IOException("Unexpected code " + response);
                } else {
                    String jsonResponse = response.body().string();
                    System.out.println("Upload Response >>> " + jsonResponse);
                    uploadedFiles.add(songPath);
                    // Update UI on main thread
                    ((Activity)context).runOnUiThread(() -> {
                        Toast.makeText(context, "Upload successful!", Toast.LENGTH_SHORT).show();
                        if (holder != null) {
                            holder.recdonpost.setVisibility(View.VISIBLE);
                            holder.notdone.setVisibility(View.GONE);
                        }
                    });
                }
            }
        });
    }

    // Modern network connectivity check (works on Android 10+)
    private boolean isNetworkConnected() {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            return capabilities != null && (
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
            );
        }
        return false;
    }

    @Override
    public int getItemCount() {
        return songNames.size();
    }

    public static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView textView, seekBarHint;
        TextView playsong, pauseRec;
        public static SeekBar seekBar;
        CardView playerCard, cardView1;
        ImageView recdonpost, notdone;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.card_item);
            playsong = itemView.findViewById(R.id.recplay);
            seekBarHint = itemView.findViewById(R.id.songDur);
            seekBar = itemView.findViewById(R.id.seekbar);
            playerCard = itemView.findViewById(R.id.playerCard);
            cardView1 = itemView.findViewById(R.id.layout1);
            pauseRec = itemView.findViewById(R.id.recPause);
            recdonpost = itemView.findViewById(R.id.recdonpost); // Ensure this ID exists in your layout
            notdone = itemView.findViewById(R.id.notdone); // Ensure this ID exists in your layout
        }
    }

    private String calculateDuration(int duration) {
        String finalDuration = "";
        long minutes = TimeUnit.MILLISECONDS.toMinutes(duration);
        long seconds = TimeUnit.MILLISECONDS.toSeconds(duration);
        if (minutes == 0) {
            finalDuration = "0:" + seconds;
        } else {
            if (seconds >= 60) {
                long sec = seconds - (minutes * 60);
                finalDuration = minutes + ":" + sec;
            }
        }
        return finalDuration;
    }
}

How to Use the Modified Adapter:

When adding a new audio file to the RecyclerView, call the addNewSong() method instead of directly modifying the songNames list:

// Example in your Activity/Fragment
recyclerViewAdapter.addNewSong("/storage/emulated/0/MyRecordings/new_call.mp3");

Additional Notes:

  1. Pending Uploads: For offline scenarios, implement a pending upload queue using WorkManager or a BroadcastReceiver to retry when the network is restored.
  2. Permissions: Ensure your app has INTERNET, READ_EXTERNAL_STORAGE (Android <13), or READ_MEDIA_AUDIO (Android 13+) permissions.
  3. Memory Leaks: Consider releasing MediaPlayer instances in onViewRecycled() to avoid memory leaks.
  4. Upload Status UI: Make sure recdonpost and notdone ImageViews exist in your record_card layout to show upload success/failure.

内容的提问来源于stack exchange,提问作者Rahul K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:00:47