0

Я разрабатываю приложение под Android, которое обрабатывает растровое изображение и применяет фильтры графического процессора на растровом изображении. Поскольку это может быть медленным, я решил установить «изображение по умолчанию», например, фальшивое изображение, которое отображается до тех пор, пока изображение, которое я хочу отфильтровать, не будет выполнено.Фоновая задача Android для UI

До этого я ожидал, что растровое изображение будет изменено до отображения, но оно не дает приятного ощущения от пользователя.

Проблема в том, что у меня есть предупреждение на системном уровне поговорке:

System.err﹕ android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

Я видел несколько потоков, которые показывают, что я должен использовать runOnUiThread, но я не знаю, как заставить его работать .. вот код моих приложений

Активность FilterActivity, получает URI, который содержит путь к файлу. Метод FilterPreview обрабатывает класс, которому удастся приостановить действие, которое я хочу сделать.

public class FiltersActivity extends Activity { 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_filters); 

     mFiltersView = (ListView) findViewById(R.id.filters_place_holder); 
     ViewGroup.LayoutParams params = mFiltersView.getLayoutParams(); 

     Intent intent = getIntent(); 
     mSnapShotUri = intent.getData(); 
     getBitmapFromURI(mSnapShotUri); 
     .... 

    private void getBitmapFromURI(Uri uri) { 
     try { 
      mSnapShot = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri); 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
      Log.e(TAG, "File not found"); 
     } 
     finally { 
      mPreviewBitmap = Bitmap.createScaledBitmap(mBitmap, PreviewSizeWidth, PreviewSizeHeight, false); 
      FiltersPreview(); 
     } 
    } 

    private void FiltersPreview() { 

     boolean mPreview = true; 
     mFiltersView.setAdapter(new CameraImageFiltersAdapter(this, mSnapShot, mPreviewBitmap, mPreview)); 
     mFiltersView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      public void onItemClick(AdapterView<?> parent, View v, int position, long id) { 

       CameraFiltersFactory effect = (CameraFiltersFactory) v.findViewById(R.id.filteredImage).getTag(); 
       effect.save(new GPUImage.OnPictureSavedListener() { 

        @Override public void onPictureSaved(Uri uri) { 

         Intent previewIntent = new Intent(FiltersActivity.this, PreviewActivity.class); 
         previewIntent.setData(uri); 
         startActivityForResult(previewIntent, 0); 

        } 
       }); 
      } 
     }); 
    } 

В моем приложении, ниже часть замедляя UI, так как я не использую фоновую задачу/нить для обновления пользовательского интерфейса.

 mFiltersView.setAdapter(new CameraImageFiltersAdapter(this, mSnapShot, mPreviewBitmap, mPreview)); 

CameraImageFiltersAdapter класса (stub_id это поддельное изображение, отображаемое в процессе применения фильтров)

public CameraImageFiltersAdapter(Context c, Bitmap original, Bitmap current, boolean isPreview) { 
     .... 
     mExecutorService = Executors.newFixedThreadPool(5); 

    } 

    @SuppressLint("InflateParams") 
    public View getView(int position, View convertView, ViewGroup parent) { 

     ImageView filteredImage; 

     if (convertView == null) { 

      convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item_filter, null); 
      filteredImage = (ImageView) convertView.findViewById(R.id.filteredImage); 
      filteredImage.setImageResource(stub_id); 
      queueFiltered(filteredImage, position); 
     } 

     return convertView; 
    } 

    private void queueFiltered(ImageView imageView, int position) { 
     CameraFiltersFactory holder = new CameraFiltersFactory(mContext, imageView); 
     mExecutorService.submit(new FilterLoader(holder, position)); 

    } 

    class FilterLoader implements Runnable { 
     CameraFiltersFactory FilterToLoad; 
     int FilterPosition; 

     FilterLoader(CameraFiltersFactory FilterToLoad, int pos) { 
      this.FilterToLoad = FilterToLoad; 
      this.FilterPosition = pos; 
     } 

     @Override 
     public void run() { 
      try { 
       FilterToLoad.setResources(mOriginalBitmap, mCurrentBitmap, mFilterIds[FilterPosition], mPreview); 
      } catch (Throwable th) { 
       th.printStackTrace(); 
      } 
     } 
    } 

Любой идею?

ответ

0

Вы не можете вносить изменения в представления в потоки ThreadPool, используйте обработчик основного потока, чтобы опубликовать сообщение и обработать его в основном потоке. Или используя AsyncTask как этот Processing Bitmaps Off the UI Thread

0

передать деятельность в качестве параметра для адаптера, а затем вызвать:

activity.runOnUiThread(new Runnable() { 
         @Override 
         public void run() { 
          //change the image here 
         } 
        }); 
Смежные вопросы