Oi Felipe, tudo bem?
Uma forma de você notificar a activity seria por meio do designer pattern Delegate.
Considerando o contexto no qual você mencionou, basicamente você faria com que a sua activity implementasse uma interface que representasse o comportamento que você espera, por exemplo a seguinte interface:
public interface AtualizadorDeLista {
public void atualiza(List<Aluno> alunos);
}
Então a activity ficaria assim:
public class ListaAlunoActivity extends AppCompatActivity implements AtualizadorDeLista {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//código
new ReceberDadosTask(this).execute();
}
@Override
public void atualiza(List<Aluno> alunos) {
//código que atualiza lista
}
}
Na sua AsyncTask, basicamente você receberia a interface na qual você implementou na Activity, pois dessa forma, você garante que qualquer um que usar essa async task vai ter o método que atualiza lista:
class ReceberDadosTask extends AsyncTask {
private AtualizadorDeLista atualizadorDeLista;
public ReceberDadosTask(AtualizadorDeLista atualizadorDeLista) {
this.atualizadorDeLista = atualizadorDeLista;
}
@Override
protected List<Aluno> doInBackground(Object[] params) {
List<Aluno> alunos = getAlunos();
return alunos;
}
@Override
protected void onPreExecute(List<Aluno> alunos) {
super.onPreExecute();
atualizadorDeLista.atualiza(alunos);
}
}
Essa é uma das técnicas que usamos para poder realizar essa comunicação. Sim, ela desacopla um pouco, porém ainda sim mantém o acoplamento com a interface...
Uma outra maneira é o uso por meio do eventbus que é uma biblioteca que permite enviar mensagens entre entidades do Android. No curso de sincronização de Android e Web Service é ensinada duas bibliotecas que facilita a vida do desenvolvedor para realizar o que você pretende fazer.
Espero ter ajudado.
Abraços.