#java #android #list
Постараюсь преподнести вопрос корректно (открыт для замечаний/правок). Начну пожалуй с начала. Есть кнопка по нажатию на которую открывается диалог. В диалоге пользователь может вставить ссылку из vimeo и youtube. После того, как ссылка вставлена в поле диалога и нажата кнопка "OK", в методе getIdUrl вытаскивается id из ссылки, после чего добавляется сама картинка из видео(preview) - пользователь(грубо говоря) видит как добавилась картинка из этого видео(следовательно видео загружено). На данный момент, приложение реализовано так, что пользователь может добавлять n-ое кол-во видео(с одинаковыми ссылками), что само собой неприемлемо. Задача заключается в поиске решения данной проблемы, а именно: Добавить возможность для пользователя добавления не более 10 файлов. Если ссылка повторяется(url видео), не добавлять его. Отрывок диалога: public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); Toast.makeText(getContext(), "ОК", Toast.LENGTH_SHORT).show(); String string = input.getText().toString(); getIdUrl(string, pos); } И часть реализации метода getIdUrl для youtube: void getIdUrl(String url, int position) { String video_id = ""; String expression = ""; if (url != null && url.trim().length() > 0 && url.matches(".*\\byoutube\\b.*")) { expression = "^.*((youtu.be" + "\\/)" + "|(v\\/)|(\\/u\\/w\\/)|(embed\\/)|(watch\\?))\\??v?=?([^#\\&\\?]*).*"; CharSequence input = url; Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(input); if (matcher.matches()) { String groupIndex1 = matcher.group(7); if (groupIndex1 != null && groupIndex1.length() == 11) video_id = groupIndex1; } ImageUpload imageUpload = new ImageUpload(); imageUpload.setLoadImage(true); OutputMetadata outputMetadata = new OutputMetadata(); outputMetadata.setVideoUrl("http://img.youtube.com/vi/" + video_id + "/0.jpg"); outputMetadata.setFilename("http://img.youtube.com/vi/" + video_id + "/0.jpg"); imageUpload.setOutputMetadata(outputMetadata); controlList.get(position).getImageUploads().add(imageUpload); adapterForm.notifyDataSetChanged(); Дополнительно к разбору: Модель VideoUpload public class VideoUpload { @SerializedName("id") @Expose private String id; @SerializedName("videoUrl") @Expose String videoUrl; @SerializedName("user_portrait_huge") @Expose private String userPortraitHuge; @SerializedName("url") @Expose private String url; public String getUserPortraitHuge() { return userPortraitHuge; } Прописаны все get'ры и set'ры. Метод contains(во фрагменте) public boolean contains(VideoUpload newVideoUpload) { for (VideoUpload videoUpload : videoUploads) { if (videoUpload.getUrl().equals(newVideoUpload.getUrl())) return true; } return false; }
Ответы
Ответ 1
Постановка задачи: По ссылке на видео с youtube.com или vimeo.com получить превью видео и отобразить его в списке на экране. При этом: Максимально можно добавить 10 видео; Не добавлять уже существующие видео. Превью можно добавить по трем типам ссылок: https://www.youtube.com/watch?v=XXXXXXXXXXX https://youtu.be/XXXXXXXXXXX https://vimeo.com/XXXXXXXXX Решение: Создаем activity_video_preview.xml:Создаем item_video_preview.xml: Создаем (для удобства) интерфейс VideoTypes: public interface VideoTypes { int TYPE_UNKNOWN = 0; int TYPE_YOUTUBE = 1; int TYPE_VIMEO = 2; } Создаем класс модели данных VideoPreview: public class VideoPreview { private String mVideoLink; private String mPreviewLink; public VideoPreview(String videoLink, String previewLink) { mVideoLink = videoLink; mPreviewLink = previewLink; } public String getVideoLink() { return mVideoLink; } public String getPreviewLink() { return mPreviewLink; } } Создаем класс VideoMethods для обработки ссылок на видео: public class VideoMethods implements VideoTypes { public static int getLinkType(String link) { Pattern pattern = Pattern.compile("^https:\\/\\/www\\.(youtube\\.com)\\/watch\\?v=[\\w-]{11}$|^https:\\/\\/(youtu\\.be)\\/[\\w-]{11}$|^https:\\/\\/(vimeo\\.com)\\/[0-9]*$"); Matcher matcher = pattern.matcher(link); if (!matcher.matches()) return TYPE_UNKNOWN; for (int i=1; i<=matcher.groupCount(); i++) { if (matcher.group(i) != null) { switch (i) { case 1: case 2: return TYPE_YOUTUBE; case 3: return TYPE_VIMEO; default: return TYPE_UNKNOWN; } } } return TYPE_UNKNOWN; } public static String getId(String link) { Pattern pattern = Pattern.compile("^https:\\/\\/www\\.youtube\\.com\\/watch\\?v=([\\w-]{11})$|^https:\\/\\/youtu\\.be\\/([\\w-]{11})$|^https:\\/\\/vimeo\\.com\\/([0-9]*)$"); Matcher matcher = pattern.matcher(link); matcher.matches(); for (int i=1; i<=matcher.groupCount(); i++) { if (matcher.group(i) != null) { return matcher.group(i); } } return null; } } Адаптер для RecyclerView: public class DataAdapter extends RecyclerView.Adapter { private ArrayList mItems; private Context mContext; public DataAdapter(Context context) { mContext = context; mItems = new ArrayList<>(); } @Override public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_video_preview, viewGroup, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { viewHolder.mPreviewLinkTextView.setText(mItems.get(i).getVideoLink()); viewHolder.mPreviewLinkPreviewTextView.setText(mItems.get(i).getPreviewLink()); Picasso.with(mContext).load(mItems.get(i).getPreviewLink()).resize(120, 90).into(viewHolder.mPreviewImageView); } @Override public int getItemCount() { return mItems.size(); } public void addItem(VideoPreview videoPreview) { mItems.add(videoPreview); notifyDataSetChanged(); } public boolean contains(VideoPreview newVideoPreview) { for (VideoPreview videoPreview : mItems) { if (videoPreview.getVideoLink().equals(newVideoPreview.getVideoLink())) return true; } return false; } public class ViewHolder extends RecyclerView.ViewHolder{ ImageView mPreviewImageView; TextView mPreviewLinkTextView; TextView mPreviewLinkPreviewTextView; public ViewHolder(View view) { super(view); mPreviewImageView = (ImageView) view.findViewById(R.id.item_video_preview_image_view); mPreviewLinkTextView = (TextView) view.findViewById(R.id.item_video_preview_link_text_view); mPreviewLinkPreviewTextView = (TextView) view.findViewById(R.id.item_video_preview_link_preview_text_view); } } } Ну и, наконец, VideoPreviewActivity: public class VideoPreviewActivity extends AppCompatActivity implements VideoTypes { private RecyclerView mVideoPreviewRecyclerView; private EditText mAddEditText; private Button mAddButton; private OkHttpClient httpClient; private DataAdapter mDataAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_video_preview); mVideoPreviewRecyclerView = (RecyclerView) findViewById(R.id.video_preview_recycler_view); mAddEditText = (EditText) findViewById(R.id.add_edit_text); mAddButton = (Button) findViewById(R.id.add_button); mVideoPreviewRecyclerView = (RecyclerView)findViewById(R.id.video_preview_recycler_view); mVideoPreviewRecyclerView.setHasFixedSize(true); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); mVideoPreviewRecyclerView.setLayoutManager(layoutManager); mDataAdapter = new DataAdapter(getApplicationContext()); mVideoPreviewRecyclerView.setAdapter(mDataAdapter); httpClient = new OkHttpClient(); mAddButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mDataAdapter.getItemCount() == 10) { Toast.makeText(getApplicationContext(), "You can not add more than 10 videos!", Toast.LENGTH_SHORT).show(); return; } String videoLink = mAddEditText.getText().toString(); int videoType = VideoMethods.getLinkType(videoLink); if (videoType == TYPE_UNKNOWN) { Toast.makeText(getApplicationContext(), "Incorrect link!", Toast.LENGTH_SHORT).show(); return; } mAddEditText.getText().clear(); InputMethodManager inputMethodManager = (InputMethodManager) VideoPreviewActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(VideoPreviewActivity.this.getCurrentFocus().getWindowToken(), 0); String videoId = VideoMethods.getId(videoLink); switch (videoType) { case TYPE_YOUTUBE: VideoPreview videoPreview = new VideoPreview(videoLink, "http://img.youtube.com/vi/" + videoId + "/1.jpg"); if (!mDataAdapter.contains(videoPreview)) { mDataAdapter.addItem(videoPreview); mVideoPreviewRecyclerView.scrollToPosition(mDataAdapter.getItemCount()-1); } else { Toast.makeText(getApplicationContext(), "This video already exists!", Toast.LENGTH_SHORT).show(); } break; case TYPE_VIMEO: try { getVimeoPreview(videoLink, videoId); } catch (Exception e) { Toast.makeText(getApplicationContext(), "Something going wrong!", Toast.LENGTH_SHORT).show(); } break; } } }); } public void getVimeoPreview(final String videoLink, final String videoId) throws Exception { Request request = new Request.Builder() .url("http://vimeo.com/api/v2/video/" + videoId + ".xml") .build(); httpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Toast.makeText(getApplicationContext(), "Something going wrong!", Toast.LENGTH_SHORT).show(); } @Override public void onResponse(Call call, Response response) throws IOException { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); String s = response.body().string(); Pattern p = Pattern.compile(" (.*)<\\/thumbnail_small>"); final Matcher m = p.matcher(s); m.find(); runOnUiThread(new Runnable() { @Override public void run() { VideoPreview videoPreview = new VideoPreview(videoLink, m.group(1)); if (!mDataAdapter.contains(videoPreview)) { mDataAdapter.addItem(videoPreview); mVideoPreviewRecyclerView.scrollToPosition(mDataAdapter.getItemCount()-1); } else { Toast.makeText(getApplicationContext(), "This video already exists!", Toast.LENGTH_SHORT).show(); } } }); } }); } } Не забывает добавить в build.gradle: compile 'com.squareup.okhttp3:okhttp:3.4.1' compile 'com.squareup.picasso:picasso:2.5.2' В итоге получаем: Ответ 2
Мое понимание проблемы таково: У автора есть метод public void success(ArrayListvideoUpload, Response response), в этом методе он хочет изменить данные controlList.get(pos).getImageUploads(), который, видимо, является ArrayList в соответствии с полученным ArrayList videoUpload. На данный момент он изменяет данные только первого элемента controlList.get(pos).getImageUploads() в соответствии с первым элементом ArrayList videoUpload (о чем говорит вызов метода get(...) у обоих списков с параметром 0). Исходя из всего вышесказанного следует, что размеры ArrayList videoUpload и controlList.get(pos).getImageUploads() должны совпадать. Таким образом, решением проблемы будет такой код метода success(...): @Override public void success(ArrayList videoUpload, Response response) { for(int i=0; i videoUpload, Response response) { ImageUpload imageUpload = new ImageUpload(); imageUpload.setLoadImage(true); imageUpload.getOutputMetadata().setVideoUrl(videoUpload.get().getUserPortraitHuge()); imageUpload.getOutputMetadata().setFilename(videoUpload.get().getUserPortraitHuge()); } Подскажите какой value можно вставить в значение get(?)? Любое целое число i, такое, что 0 <= i < videoUpload.size() в зависимости от того, какой элемент списка videoUpload Вы хотите получить.
Комментариев нет:
Отправить комментарий