Этот ответ может быть запоздалым, но я хотел бы упомянуть несколько вещей, когда ваш Activity
зависит от AsyncTask
. Это поможет вам предотвратить сбои и управление памятью. Как уже упоминалось в приведенных выше ответах, переходите к interface
, мы также говорим, что они обратные вызовы. Они будут работать как информатор, но никогда не будут отправлять ссылки Activity
или interface
всегда использовать слабую ссылку в этих случаях.
Пожалуйста, обратитесь к скриншоту ниже, чтобы узнать, как это может вызвать проблемы.
Как вы можете видеть, начали ли мы AsyncTask
с сильной ссылки, тогда нет гарантии, что наш Activity
/ Fragment
будет до тех пор, пока мы не получим данные, поэтому было бы лучше использовать WeakReference
в этих случаях, и это также поможет в управлении памятью, поскольку мы никогда не будем придерживаться сильной ссылки на наш Activity
, тогда он будет иметь право на сбор мусора после его искажения.
Проверьте ниже фрагмент кода, чтобы узнать, как использовать awesome WeakReference -
MyTaskInformer.java
Интерфейс, который будет работать как информатор.
public interface MyTaskInformer {
void onTaskDone(String output);
}
MySmallAsyncTask.java
AsyncTask выполняет длительную задачу, которая будет использовать WeakReference
.
public class MySmallAsyncTask extends AsyncTask {
// ***** Hold weak reference *****
private WeakReference mCallBack;
public MySmallAsyncTask(MyTaskInformer callback) {
this.mCallBack = new WeakReference<>(callback);
}
@Override
protected String doInBackground(String... params) {
// Here do whatever your task is like reading/writing file
// or read data from your server or any other heavy task
// Let us suppose here you get response, just return it
final String output = "Any out, mine is just demo output";
// Return it from here to post execute
return output;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
// Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask
// Make sure your caller is active
final MyTaskInformer callBack = mCallBack.get();
if(callBack != null) {
callBack.onTaskDone(s);
}
}
}
MainActivity.java
Этот класс используется для запуска моего AsyncTask
реализации interface
в этом классе и override
этот обязательный метод.
public class MainActivity extends Activity implements MyTaskInformer {
private TextView mMyTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyTextView = (TextView) findViewById(R.id.tv_text_view);
// Start your AsyncTask and pass reference of MyTaskInformer in constructor
new MySmallAsyncTask(this).execute();
}
@Override
public void onTaskDone(String output) {
// Here you will receive output only if your Activity is alive.
// no need to add checks like if(!isFinishing())
mMyTextView.setText(output);
}
}
Это - общее препятствие при использовании ScrolledComposite
. Когда это становится столь маленьким, что полосу прокрутки нужно показать, клиентское управление должно уменьшиться горизонтально для создания места для полосы прокрутки. Это имеет побочный эффект того, чтобы заставлять некоторые маркировки перенести строки, которые переместили следующие средства управления дальше вниз, которые увеличили минимальную высоту, необходимую довольному составной объект.
Необходимо прислушаться к изменениям ширины на довольном составной объект (mParent
), вычислите минимальную высоту снова, учитывая новую ширину содержания и вызов setMinHeight()
на прокрученном составном объекте с новой высотой.
public void createPartControl(Composite parent) {
parent.setLayout(new FillLayout());
ScrolledComposite scrollBox = new ScrolledComposite(parent, SWT.V_SCROLL);
scrollBox.setExpandHorizontal(true);
scrollBox.setExpandVertical(true);
// Using 0 here ensures the horizontal scroll bar will never appear. If
// you want the horizontal bar to appear at some threshold (say 100
// pixels) then send that value instead.
scrollBox.setMinWidth(0);
mParent = new Composite(scrollBox, SWT.NONE);
FormLayout layout = new FormLayout();
mParent.setLayout(layout);
// Adds a bunch of controls here
mParent.addListener(SWT.Resize, new Listener() {
int width = -1;
public void handleEvent(Event e) {
int newWidth = mParent.getSize().x;
if (newWidth != width) {
scrollBox.setMinHeight(mParent.computeSize(newWidth, SWT.DEFAULT).y);
width = newWidth;
}
}
}
// Wait until here to set content pane. This way the resize listener will
// fire when the scrolled composite first resizes mParent, which in turn
// computes the minimum height and calls setMinHeight()
scrollBox.setContent(mParent);
}
В прислушивании к изменениям размера обратите внимание, что мы игнорируем, любой изменяет размер событий, где ширина остается такой же. Это вызвано тем, что изменения в высоте содержания не влияют на минимальную высоту содержания, пока ширина является тем же.
Если я не ошибаюсь, необходимо подкачать
mParent.layout();
и
mParent.setSize(mParent.computeSize(SWT.DEFAULT, SWT.DEFAULT, true));
так, чтобы Вы имели:
public void createPartControl(Composite parent) {
parent.setLayout(new FillLayout());
ScrolledComposite scrollBox = new ScrolledComposite(parent, SWT.V_SCROLL);
scrollBox.setExpandHorizontal(true);
mParent = new Composite(scrollBox, SWT.NONE);
scrollBox.setContent(mParent);
FormLayout layout = new FormLayout();
mParent.setLayout(layout);
// Adds a bunch of controls here
mParent.setSize(mParent.computeSize(SWT.DEFAULT, SWT.DEFAULT, true));
mParent.layout();
}
Разве Вы не должны повторно вычислять размер ползунка после расположения?
Попытайтесь установить .setMinWidth и .setMinHeight на ScrolledComposite, после того как расположение было сделано, передав его размер основного составного объекта.